@wix/agent-skills 1.19.2 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/references/SERVICE_PLUGIN.md +14 -1
  3. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +7 -6
  4. package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +4 -0
  5. package/skills/wix-app/references/service-plugin/AVAILABILITY-TIME-SLOTS-CONFIGURATION.md +118 -0
  6. package/skills/wix-app/references/service-plugin/BOOKING-POLICY.md +65 -0
  7. package/skills/wix-app/references/service-plugin/BOOKINGS-PRICING.md +71 -0
  8. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +11 -3
  9. package/skills/wix-app/references/service-plugin/BOOKINGS-VALIDATION.md +137 -0
  10. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +23 -16
  11. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
  12. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +4 -2
  13. package/skills/wix-app/references/service-plugin/REALTIME-PERMISSIONS.md +45 -0
  14. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +15 -0
  15. package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +4 -0
  16. package/skills/wix-app/references/service-plugin/VALIDATIONS.md +4 -0
  17. package/skills/wix-headless/references/CAPABILITIES.md +2 -2
  18. package/skills/wix-headless/references/inline-recipes/experience-store.md +4 -3
  19. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +98 -18
  20. package/skills/wix-headless/references/managed/DEPLOYMENT.md +8 -8
  21. package/skills/wix-headless-fast/SKILL.md +200 -34
  22. package/skills/wix-headless-fast/entry/skill.md +10 -2
  23. package/skills/wix-headless-fast/install/attach.mjs +253 -0
  24. package/skills/wix-headless-fast/install/deploy.mjs +109 -9
  25. package/skills/wix-headless-fast/install/fast-path.mjs +28 -31
  26. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +224 -60
  27. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +2 -3
  28. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +2 -3
  29. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +24 -116
  30. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +16 -64
  31. package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +137 -0
  32. package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +78 -0
  33. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +117 -0
  34. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +13 -60
  35. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +47 -0
  36. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +10 -28
  37. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +2 -4
  38. package/skills/wix-headless-fast/references/blog/rest/posts.ts +42 -0
  39. package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +62 -0
  40. package/skills/wix-headless-fast/references/blog/seed/SEED.md +9 -0
  41. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +179 -33
  42. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +2 -1
  43. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +26 -132
  44. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +18 -49
  45. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +218 -0
  46. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +169 -0
  47. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +57 -142
  48. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +92 -0
  49. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +90 -0
  50. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +22 -61
  51. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +3 -1
  52. package/skills/wix-headless-fast/references/bookings/rest/booking.ts +113 -0
  53. package/skills/wix-headless-fast/references/bookings/rest/services.ts +55 -0
  54. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +10 -0
  55. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +236 -62
  56. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +19 -52
  57. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +16 -36
  58. package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +158 -0
  59. package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +93 -0
  60. package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +177 -0
  61. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +13 -41
  62. package/skills/wix-headless-fast/references/cms/rest/items.ts +125 -0
  63. package/skills/wix-headless-fast/references/cms/seed/SEED.md +9 -0
  64. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +239 -83
  65. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +1 -1
  66. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +7 -5
  67. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +2 -2
  68. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +28 -110
  69. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +19 -54
  70. package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +130 -0
  71. package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +97 -0
  72. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +13 -94
  73. package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +113 -0
  74. package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +156 -0
  75. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +38 -69
  76. package/skills/wix-headless-fast/references/events/rest/events.ts +57 -0
  77. package/skills/wix-headless-fast/references/events/rest/registration.ts +83 -0
  78. package/skills/wix-headless-fast/references/events/seed/SEED.md +9 -0
  79. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +214 -26
  80. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +35 -267
  81. package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +332 -0
  82. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +238 -0
  83. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +28 -243
  84. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +216 -0
  85. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +32 -204
  86. package/skills/wix-headless-fast/references/forms/rest/forms.ts +34 -0
  87. package/skills/wix-headless-fast/references/forms/rest/submissions.ts +56 -0
  88. package/skills/wix-headless-fast/references/forms/seed/SEED.md +8 -0
  89. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +15 -8
  90. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +314 -63
  91. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +1 -1
  92. package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +105 -0
  93. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +36 -65
  94. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +1 -1
  95. package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +43 -0
  96. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +11 -32
  97. package/skills/wix-headless-fast/references/members/rest/auth.ts +215 -0
  98. package/skills/wix-headless-fast/references/members/rest/members.ts +26 -0
  99. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +238 -59
  100. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +2 -2
  101. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +2 -2
  102. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +35 -0
  103. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +8 -38
  104. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +23 -50
  105. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +16 -34
  106. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +22 -49
  107. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +82 -0
  108. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +58 -0
  109. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +177 -0
  110. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +31 -118
  111. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +81 -0
  112. package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +75 -0
  113. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +8 -0
  114. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +212 -51
  115. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +9 -20
  116. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +7 -32
  117. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +41 -0
  118. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +12 -33
  119. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +17 -34
  120. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +54 -0
  121. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +106 -0
  122. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +64 -0
  123. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +7 -55
  124. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +43 -0
  125. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +11 -34
  126. package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +31 -0
  127. package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +20 -0
  128. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +8 -0
  129. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +240 -47
  130. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +2 -2
  131. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +2 -2
  132. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +14 -35
  133. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +28 -171
  134. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +155 -0
  135. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +89 -0
  136. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +23 -117
  137. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +124 -0
  138. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +45 -114
  139. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +193 -0
  140. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +94 -0
  141. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +15 -87
  142. package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +60 -0
  143. package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +169 -0
  144. package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +68 -0
  145. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +8 -0
  146. package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +23 -0
  147. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +55 -1
  148. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +13 -0
  149. package/skills/wix-headless-fast/references/shared/rest/client.ts +155 -0
  150. package/skills/wix-headless-fast/references/shared/rest/config.ts +3 -0
  151. package/skills/wix-headless-fast/references/shared/rest/media.ts +65 -0
  152. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +371 -81
  153. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +37 -3
  154. package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +266 -0
  155. package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +95 -0
  156. package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +136 -0
  157. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +29 -130
  158. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +26 -182
  159. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +121 -0
  160. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +53 -136
  161. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +309 -0
  162. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +73 -230
  163. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +147 -0
  164. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +289 -0
  165. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +62 -4
  166. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +21 -2
  167. package/skills/wix-headless-fast/references/storefront/rest/cart.ts +132 -0
  168. package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +123 -0
  169. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +25 -5
  170. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +24 -0
  171. package/skills/wix-manage/SKILL.md +4 -1
  172. package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
  173. package/skills/wix-manage/references/events/create-wix-event.md +46 -0
  174. package/skills/wix-manage/references/events/manage-wix-events.md +51 -1
  175. package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +6 -6
  176. package/skills/wix-manage/references/seo/manage-seo-suggestions.md +351 -0
  177. package/skills/wix-vibe-headless/install/deploy.cjs +33 -2
  178. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +1 -1
  179. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -4
  180. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +1 -1
  181. package/skills/wix-vibe-headless/platforms/base44.md +19 -4
  182. package/skills/wix-vibe-headless/platforms/generic.md +6 -0
  183. package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +30 -0
  184. package/skills/wix-vibe-headless/references/_shared/routing.md +86 -0
  185. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +44 -0
  186. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +1 -1
  187. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +1 -1
  188. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +1 -1
  189. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +1 -1
  190. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +1 -1
  191. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +42 -0
  192. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +1 -1
  193. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +1 -1
  194. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +42 -0
  195. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +1 -1
  196. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +1 -1
  197. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +42 -0
  198. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +1 -1
  199. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +1 -1
  200. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +1 -1
  201. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +43 -0
  202. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +1 -1
  203. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +1 -1
  204. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +1 -1
  205. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +1 -1
  206. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +43 -0
  207. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +1 -1
  208. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +1 -1
  209. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +36 -0
  210. package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +9 -0
  211. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +42 -41
  212. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +7 -1
  213. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +3 -0
  214. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +6 -0
  215. package/skills/wix-headless-fast/install/pin-agents-md.mjs +0 -57
@@ -0,0 +1,155 @@
1
+ // The one auth seam for every Wix REST call — the twin of app/wix/sdk.ts, over fetch. No
2
+ // dependencies. deploy.mjs --stack static copies it flat into js/wix/ next to the core files and
3
+ // strips it to JS (comments kept); a port to another language reads it as the specification.
4
+ // Imports carry the .js suffix so the stripped output runs as browser ESM unchanged.
5
+ //
6
+ // WIX_CLIENT_ID is the public OAuth client id (`appId` in wix.config.json). It is NOT a secret — it
7
+ // only mints anonymous VISITOR tokens — so it is fine in page source. deploy.mjs writes ./config.
8
+ //
9
+ // THE TOKEN IS THE CART. A visitor token is the shopper's identity: their cart lives on it. Mint
10
+ // once per shopper, persist it, refresh it — never mint per request (a fresh token is a new visitor
11
+ // with an empty cart). Where it persists depends on where this code runs:
12
+ // browser — localStorage, keyed by client id so two sites on one origin don't share a token
13
+ // (what this file does).
14
+ // server (a Python/PHP/Go port) — the SHOPPER'S SESSION, one token set per shopper. Never one
15
+ // process-wide token for everyone: that is one shared cart for all visitors.
16
+ // This is the only part of a port that isn't line-for-line.
17
+ // docs: https://dev.wix.com/docs/go-headless/coding/authentication/visitors.md
18
+ import { WIX_CLIENT_ID } from "./config.js";
19
+
20
+ export const WIX_API_BASE = "https://www.wixapis.com";
21
+ const TOKEN_URL = `${WIX_API_BASE}/oauth2/token`;
22
+ const STORAGE_KEY = `wix-visitor-${WIX_CLIENT_ID}`;
23
+
24
+ export interface Tokens {
25
+ accessToken: string;
26
+ refreshToken: string;
27
+ /** Epoch ms. */
28
+ expiresAt: number;
29
+ /** Whose tokens: absent or "visitor" for an anonymous visitor, "member" after a login (a vertical's rest/auth.ts). */
30
+ role?: "visitor" | "member";
31
+ }
32
+
33
+ /** Swap this for a server-session-backed store in a port; the browser default is localStorage. */
34
+ export interface TokenStore {
35
+ load(): Tokens | null;
36
+ save(tokens: Tokens): void;
37
+ }
38
+
39
+ let memory: Tokens | null = null;
40
+ export const browserTokenStore: TokenStore = {
41
+ load() {
42
+ if (memory) return memory;
43
+ if (typeof localStorage === "undefined") return null;
44
+ try {
45
+ const raw = localStorage.getItem(STORAGE_KEY);
46
+ if (raw) memory = JSON.parse(raw) as Tokens;
47
+ } catch {
48
+ /* disabled or corrupt storage — mint a fresh visitor */
49
+ }
50
+ return memory;
51
+ },
52
+ save(tokens) {
53
+ memory = tokens;
54
+ if (typeof localStorage === "undefined") return;
55
+ try {
56
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(tokens));
57
+ } catch {
58
+ /* storage full or disabled — the session just won't survive a reload */
59
+ }
60
+ },
61
+ };
62
+ let store: TokenStore = browserTokenStore;
63
+ /** A port calls this once with its session-backed store. */
64
+ export function useTokenStore(s: TokenStore): void {
65
+ store = s;
66
+ }
67
+
68
+ // POST /oauth2/token — grantType "anonymous" mints a visitor; "refresh_token" renews and KEEPS the
69
+ // identity (a member refresh token yields member tokens); "authorization_code" + codeVerifier turns
70
+ // a login's authorization code into MEMBER tokens (a vertical's rest/auth.ts). `role` records which.
71
+ export async function mintTokens(body: Record<string, string>, role: Tokens["role"] = "visitor"): Promise<Tokens> {
72
+ const res = await fetch(TOKEN_URL, {
73
+ method: "POST",
74
+ headers: { "Content-Type": "application/json" },
75
+ body: JSON.stringify({ clientId: WIX_CLIENT_ID, ...body }),
76
+ });
77
+ if (!res.ok) throw new Error(`Wix auth failed (${res.status}).`);
78
+ const data = await res.json();
79
+ return { accessToken: data.access_token, refreshToken: data.refresh_token, expiresAt: Date.now() + data.expires_in * 1000, role };
80
+ }
81
+
82
+ /** The persisted token set as it is (possibly expired), or null before the first mint. */
83
+ export function loadTokens(): Tokens | null {
84
+ return store.load();
85
+ }
86
+
87
+ /** Adopt a token set — a member's after login. Every call from here on runs as that identity. */
88
+ export function setTokens(tokens: Tokens): void {
89
+ store.save(tokens);
90
+ }
91
+
92
+ /** Drop the current identity (logout): the next call mints a fresh anonymous visitor. */
93
+ export function clearTokens(): void {
94
+ store.save({ accessToken: "", refreshToken: "", expiresAt: 0 });
95
+ }
96
+
97
+ /** A valid access token: cached, refreshed when expired, minted on first use. */
98
+ export async function accessToken(): Promise<string> {
99
+ const t = store.load();
100
+ if (t && t.expiresAt - 60_000 > Date.now()) return t.accessToken;
101
+ let fresh: Tokens | undefined;
102
+ if (t?.refreshToken) {
103
+ try {
104
+ fresh = await mintTokens({ grantType: "refresh_token", refreshToken: t.refreshToken }, t.role ?? "visitor");
105
+ } catch {
106
+ /* fall through to a new visitor */
107
+ }
108
+ }
109
+ fresh ??= await mintTokens({ grantType: "anonymous" });
110
+ store.save(fresh);
111
+ return fresh.accessToken;
112
+ }
113
+
114
+ export class WixApiError extends Error {
115
+ /** The response's `details` as Wix sent it (applicationError, validationError) — for callers that map codes. */
116
+ public details?: Record<string, any>;
117
+ constructor(message: string, public status: number, public code?: string, details?: Record<string, any>) {
118
+ super(message);
119
+ this.details = details;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Every Wix call goes through here. `path` is relative to WIX_API_BASE; `query` becomes the query
125
+ * string (an array repeats the key: fields=A&fields=B). Throws WixApiError on a non-2xx, including
126
+ * 404 — callers that treat 404 as "not found" catch it. The header carries the RAW access token,
127
+ * no "Bearer " prefix.
128
+ */
129
+ export async function wixRequest<T = any>(
130
+ path: string,
131
+ { method = "POST", body, query }: { method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; body?: unknown; query?: Record<string, string | readonly string[]> } = {},
132
+ ): Promise<T> {
133
+ const url = new URL(path, WIX_API_BASE);
134
+ for (const [k, v] of Object.entries(query ?? {})) {
135
+ for (const item of Array.isArray(v) ? v : [v as string]) url.searchParams.append(k, String(item));
136
+ }
137
+ const res = await fetch(url, {
138
+ method,
139
+ headers: { Authorization: await accessToken(), "Content-Type": "application/json" },
140
+ body: body === undefined ? undefined : JSON.stringify(body),
141
+ });
142
+ if (!res.ok) {
143
+ let message = "", code: string | undefined, details: Record<string, any> | undefined;
144
+ try {
145
+ const j = await res.json();
146
+ message = j?.message ?? "";
147
+ code = j?.details?.applicationError?.code;
148
+ details = j?.details;
149
+ } catch {
150
+ /* no JSON body */
151
+ }
152
+ throw new WixApiError(message || `${method} ${url.pathname} failed (${res.status}).`, res.status, code, details);
153
+ }
154
+ return (res.status === 204 ? null : await res.json()) as T;
155
+ }
@@ -0,0 +1,3 @@
1
+ // Written by install/deploy.mjs --stack static from wix.config.json (or --client-id).
2
+ // The public OAuth client id — not a secret: it only mints anonymous visitor tokens.
3
+ export const WIX_CLIENT_ID: string = "";
@@ -0,0 +1,65 @@
1
+ // Wix media → browser-loadable URLs — the twin of app/wix/media.ts, without the SDK.
2
+ //
3
+ // A media value arrives as either an absolute https://static.wixstatic.com/... URL or a raw
4
+ // `wix:image://v1/<file>/<name>#originWidth=W&originHeight=H` identifier a browser cannot load
5
+ // (ERR_UNKNOWN_URL_SCHEME). The raw form is scaled through this ONE URL shape; any other hand-built
6
+ // form 403s: https://static.wixstatic.com/media/<file>/v1/fill/w_<W>,h_<H>,al_c,q_90/<file>
7
+ const STATIC = "https://static.wixstatic.com/media";
8
+ const FILL = /\/v1\/fill\/w_\d+,h_\d+/;
9
+
10
+ export type MediaLike = string | null | undefined | { image?: string | null; url?: string | null };
11
+
12
+ function rawOf(value: unknown): string {
13
+ if (!value) return "";
14
+ if (typeof value === "string") return value;
15
+ const o = value as { image?: string | null; url?: string | null };
16
+ return o.image ?? o.url ?? "";
17
+ }
18
+
19
+ /** Resolve any Wix media value to a URL sized w×h ("" when absent). */
20
+ export function imgSrc(value: unknown, width = 600, height = 600): string {
21
+ const v = rawOf(value);
22
+ if (!v) return "";
23
+ if (v.startsWith("wix:image://")) {
24
+ const file = v.slice("wix:image://v1/".length).split("/")[0].split("#")[0];
25
+ return `${STATIC}/${file}/v1/fill/w_${width},h_${height},al_c,q_90/${file}`;
26
+ }
27
+ // An absolute Wix media URL (bare, or already scaled to some other size): re-issue it through the
28
+ // scaler at the requested size, so every image path lands on one shape.
29
+ const m = v.match(/^https:\/\/static\.wixstatic\.com\/media\/([^/?#]+)/);
30
+ if (m) return `${STATIC}/${m[1]}/v1/fill/w_${width},h_${height},al_c,q_90/${m[1]}`;
31
+ return v;
32
+ }
33
+
34
+ /** srcset candidates at several widths; `ratio` is height/width. "" only when there is no image. */
35
+ export function imgSrcSet(value: unknown, widths: number[] = [320, 480, 640, 960], ratio = 1): string {
36
+ const v = rawOf(value);
37
+ if (!v) return "";
38
+ if (v.startsWith("wix:image://")) return widths.map((w) => `${imgSrc(value, w, Math.round(w * ratio))} ${w}w`).join(", ");
39
+ if (v.includes("static.wixstatic.com/") && FILL.test(v)) {
40
+ return widths.map((w) => `${v.replace(FILL, `/v1/fill/w_${w},h_${Math.round(w * ratio)}`)} ${w}w`).join(", ");
41
+ }
42
+ return v;
43
+ }
44
+
45
+ /**
46
+ * Everything an <img> needs for one Wix image, so a tile can never ship `srcset` without `src`.
47
+ * Attribute names as HTML spells them — spread into a template or apply with setAttribute:
48
+ * `<img ${attrs(imgAttrs(p.imageUrl, "(min-width: 1024px) 25vw, 50vw"))} alt="…">`
49
+ * `sizes` is the width the image renders at; `ratio` is height/width. {} when there is no image.
50
+ */
51
+ export function imgAttrs(value: unknown, sizes: string, ratio = 1): Record<string, string> {
52
+ const src = imgSrc(value, 640, Math.round(640 * ratio));
53
+ if (!src) return {};
54
+ return { src, srcset: imgSrcSet(value, undefined, ratio), sizes, loading: "lazy", decoding: "async" };
55
+ }
56
+
57
+ /** The media identity before scaling — de-duplicate galleries on this, never on a resolved URL. */
58
+ export function mediaKey(value: unknown): string {
59
+ const v = rawOf(value);
60
+ if (!v) return "";
61
+ // The file id, whichever form the value takes — a raw id and a resolved URL of one photo share it.
62
+ if (v.startsWith("wix:image://")) return v.slice("wix:image://v1/".length).split("/")[0].split("#")[0];
63
+ const m = v.match(/^https:\/\/static\.wixstatic\.com\/media\/([^/?#]+)/);
64
+ return m ? m[1] : v;
65
+ }