@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.
- package/package.json +1 -1
- package/skills/wix-app/references/SERVICE_PLUGIN.md +14 -1
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +7 -6
- package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +4 -0
- package/skills/wix-app/references/service-plugin/AVAILABILITY-TIME-SLOTS-CONFIGURATION.md +118 -0
- package/skills/wix-app/references/service-plugin/BOOKING-POLICY.md +65 -0
- package/skills/wix-app/references/service-plugin/BOOKINGS-PRICING.md +71 -0
- package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +11 -3
- package/skills/wix-app/references/service-plugin/BOOKINGS-VALIDATION.md +137 -0
- package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +23 -16
- package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
- package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +4 -2
- package/skills/wix-app/references/service-plugin/REALTIME-PERMISSIONS.md +45 -0
- package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +15 -0
- package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +4 -0
- package/skills/wix-app/references/service-plugin/VALIDATIONS.md +4 -0
- package/skills/wix-headless/references/CAPABILITIES.md +2 -2
- package/skills/wix-headless/references/inline-recipes/experience-store.md +4 -3
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +98 -18
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +8 -8
- package/skills/wix-headless-fast/SKILL.md +200 -34
- package/skills/wix-headless-fast/entry/skill.md +10 -2
- package/skills/wix-headless-fast/install/attach.mjs +253 -0
- package/skills/wix-headless-fast/install/deploy.mjs +109 -9
- package/skills/wix-headless-fast/install/fast-path.mjs +28 -31
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +224 -60
- package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +2 -3
- package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +2 -3
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +24 -116
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +16 -64
- package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +137 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +78 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +117 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +13 -60
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +47 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +10 -28
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +2 -4
- package/skills/wix-headless-fast/references/blog/rest/posts.ts +42 -0
- package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +62 -0
- package/skills/wix-headless-fast/references/blog/seed/SEED.md +9 -0
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +179 -33
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +2 -1
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +26 -132
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +18 -49
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +218 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +169 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +57 -142
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +92 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +90 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +22 -61
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +3 -1
- package/skills/wix-headless-fast/references/bookings/rest/booking.ts +113 -0
- package/skills/wix-headless-fast/references/bookings/rest/services.ts +55 -0
- package/skills/wix-headless-fast/references/bookings/seed/SEED.md +10 -0
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +236 -62
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +19 -52
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +16 -36
- package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +158 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +93 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +177 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +13 -41
- package/skills/wix-headless-fast/references/cms/rest/items.ts +125 -0
- package/skills/wix-headless-fast/references/cms/seed/SEED.md +9 -0
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +239 -83
- package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +1 -1
- package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +7 -5
- package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +2 -2
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +28 -110
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +19 -54
- package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +130 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +97 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +13 -94
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +113 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +156 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +38 -69
- package/skills/wix-headless-fast/references/events/rest/events.ts +57 -0
- package/skills/wix-headless-fast/references/events/rest/registration.ts +83 -0
- package/skills/wix-headless-fast/references/events/seed/SEED.md +9 -0
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +214 -26
- package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +35 -267
- package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +332 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +238 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +28 -243
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +216 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +32 -204
- package/skills/wix-headless-fast/references/forms/rest/forms.ts +34 -0
- package/skills/wix-headless-fast/references/forms/rest/submissions.ts +56 -0
- package/skills/wix-headless-fast/references/forms/seed/SEED.md +8 -0
- package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +15 -8
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +314 -63
- package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +1 -1
- package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +105 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +36 -65
- package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +1 -1
- package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +43 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +11 -32
- package/skills/wix-headless-fast/references/members/rest/auth.ts +215 -0
- package/skills/wix-headless-fast/references/members/rest/members.ts +26 -0
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +238 -59
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +2 -2
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +2 -2
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +35 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +8 -38
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +23 -50
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +16 -34
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +22 -49
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +82 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +58 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +177 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +31 -118
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +81 -0
- package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +75 -0
- package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +8 -0
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +212 -51
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +9 -20
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +7 -32
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +41 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +12 -33
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +17 -34
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +54 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +106 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +64 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +7 -55
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +43 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +11 -34
- package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +31 -0
- package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +20 -0
- package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +8 -0
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +240 -47
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +2 -2
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +2 -2
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +14 -35
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +28 -171
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +155 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +89 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +23 -117
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +124 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +45 -114
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +193 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +94 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +15 -87
- package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +60 -0
- package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +169 -0
- package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +68 -0
- package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +8 -0
- package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +23 -0
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +55 -1
- package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +13 -0
- package/skills/wix-headless-fast/references/shared/rest/client.ts +155 -0
- package/skills/wix-headless-fast/references/shared/rest/config.ts +3 -0
- package/skills/wix-headless-fast/references/shared/rest/media.ts +65 -0
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +371 -81
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +37 -3
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +266 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +95 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +136 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +29 -130
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +26 -182
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +121 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +53 -136
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +309 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +73 -230
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +147 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +289 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +62 -4
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +21 -2
- package/skills/wix-headless-fast/references/storefront/rest/cart.ts +132 -0
- package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +123 -0
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +25 -5
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +24 -0
- package/skills/wix-manage/SKILL.md +4 -1
- package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
- package/skills/wix-manage/references/events/create-wix-event.md +46 -0
- package/skills/wix-manage/references/events/manage-wix-events.md +51 -1
- package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +6 -6
- package/skills/wix-manage/references/seo/manage-seo-suggestions.md +351 -0
- package/skills/wix-vibe-headless/install/deploy.cjs +33 -2
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +1 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -4
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +1 -1
- package/skills/wix-vibe-headless/platforms/base44.md +19 -4
- package/skills/wix-vibe-headless/platforms/generic.md +6 -0
- package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +30 -0
- package/skills/wix-vibe-headless/references/_shared/routing.md +86 -0
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +44 -0
- package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +1 -1
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +42 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +42 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +42 -0
- package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +1 -1
- package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +1 -1
- package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +43 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +43 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +36 -0
- package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +9 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +42 -41
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +7 -1
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +3 -0
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +6 -0
- 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,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
|
+
}
|