@wix/agent-skills 1.21.0 → 1.23.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.
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +71 -7
- package/skills/wix-app/references/APP_VALIDATION.md +16 -10
- package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
- package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
- package/skills/wix-app/references/SDK_MODULE_MAP.md +2 -0
- package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
- package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
- package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
- package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
- package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
- package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
- package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
- package/skills/wix-headless-fast/SKILL.md +95 -230
- package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
- package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +17 -14
- package/skills/wix-headless-fast/guides/existing-site.md +78 -0
- package/skills/wix-headless-fast/guides/migration.md +43 -0
- package/skills/wix-headless-fast/guides/reference-mode.md +100 -0
- package/skills/wix-headless-fast/install/AGENTS.md +9 -4
- package/skills/wix-headless-fast/install/agents-md.mjs +5 -1
- package/skills/wix-headless-fast/install/attach.mjs +25 -47
- package/skills/wix-headless-fast/install/check.mjs +87 -0
- package/skills/wix-headless-fast/install/context.mjs +126 -0
- package/skills/wix-headless-fast/install/deploy.mjs +106 -80
- package/skills/wix-headless-fast/install/lock.mjs +55 -0
- package/skills/wix-headless-fast/install/setup.mjs +83 -23
- package/skills/wix-headless-fast/install/templates.mjs +168 -0
- package/skills/wix-manage/SKILL.md +3 -3
- package/skills/wix-manage/references/app-installation/install-wix-apps.md +68 -2
- package/skills/wix-manage/references/contacts/bulk-label-and-unlabel-contacts.md +37 -4
- package/skills/wix-manage/references/ecommerce/ecom-pricing.md +29 -3
- package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
- package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
- package/skills/wix-manage/references/sites/site-import.md +101 -37
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -303
- package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
- package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
- package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
- package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
- package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
- package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
- package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
- package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
- package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
- package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
- package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
- package/skills/wix-headless-fast/references/blog/seed/read-site.mjs +0 -22
- package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -277
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
- package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
- package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
- package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
- package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
- package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
- package/skills/wix-headless-fast/references/bookings/seed/read-site.mjs +0 -28
- package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -355
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
- package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
- package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
- package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
- package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
- package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
- package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
- package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
- package/skills/wix-headless-fast/references/cms/seed/read-site.mjs +0 -20
- package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -307
- package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
- package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
- package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
- package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
- package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
- package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
- package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
- package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
- package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
- package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
- package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
- package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
- package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
- package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
- package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
- package/skills/wix-headless-fast/references/events/seed/read-site.mjs +0 -26
- package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +0 -276
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -340
- package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +0 -85
- package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +0 -332
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +0 -238
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +0 -54
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +0 -216
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +0 -59
- package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +0 -135
- package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +0 -10593
- package/skills/wix-headless-fast/references/forms/rest/forms.ts +0 -34
- package/skills/wix-headless-fast/references/forms/rest/submissions.ts +0 -56
- package/skills/wix-headless-fast/references/forms/seed/SEED.md +0 -116
- package/skills/wix-headless-fast/references/forms/seed/read-site.mjs +0 -20
- package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +0 -327
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -316
- package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
- package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
- package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
- package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
- package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
- package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
- package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
- package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
- package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
- package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
- package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
- package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
- package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
- package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
- package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
- package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
- package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
- package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
- package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
- package/skills/wix-headless-fast/references/members/seed/read-site.mjs +0 -15
- package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -315
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
- package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
- package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
- package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
- package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
- package/skills/wix-headless-fast/references/portfolio/seed/read-site.mjs +0 -20
- package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -256
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -296
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
- package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
- package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
- package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
- package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
- package/skills/wix-headless-fast/references/pricing-plans/seed/read-site.mjs +0 -21
- package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -360
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
- package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
- package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
- package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
- package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
- package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
- package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
- package/skills/wix-headless-fast/references/restaurants/seed/read-site.mjs +0 -25
- package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -499
- package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
- package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
- package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
- package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
- package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
- package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
- package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
- package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
- package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
- package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
- package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
- package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
- package/skills/wix-headless-fast/references/shared/seed/read-site.mjs +0 -99
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -612
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -314
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -169
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
- package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
- package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
- package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -130
- package/skills/wix-headless-fast/references/storefront/seed/read-site.mjs +0 -38
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -561
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
@import url('https://fonts.googleapis.com/css2?family=Wix+Madefor+Text:wght@400;500;600;700;800&display=swap');
|
|
2
|
-
@import 'tailwindcss';
|
|
3
|
-
|
|
4
|
-
/* ─── THE design system ─────────────────────────────────────────────────────────────────
|
|
5
|
-
Theme the entire store by editing THIS @theme block (same token family as the official
|
|
6
|
-
Wix headless templates). Every shipped component styles itself from these via Tailwind
|
|
7
|
-
utilities (bg-primary, text-muted-foreground, rounded-lg, …) — change a token, everything
|
|
8
|
-
follows. A dark theme is just flipped values (dark background/foreground, adjusted
|
|
9
|
-
secondary/border). Don't restyle shipped component markup; restyle the tokens.
|
|
10
|
-
|
|
11
|
-
Choosing values: argue polarity from the business — light is not "cheap" (wellness/food
|
|
12
|
-
usually read better light); never dark-by-default for "premium". Palette: one dominant +
|
|
13
|
-
accents from ADJACENT hues (~30° arc), 2-4 colors total. Every background/foreground pair
|
|
14
|
-
you set must hit WCAG 4.5:1 (3:1 for text ≥24px); body copy never below 16px/1.5. Derive
|
|
15
|
-
from THIS brand — a look repeated across projects is a failure, not a shortcut. The user's
|
|
16
|
-
explicit direction beats all of this except the contrast floor. */
|
|
17
|
-
@theme {
|
|
18
|
-
--color-background: hsl(0 0% 100%);
|
|
19
|
-
--color-foreground: hsl(230 24% 14%);
|
|
20
|
-
--color-primary: hsl(230 24% 14%);
|
|
21
|
-
--color-primary-foreground: hsl(0 0% 100%);
|
|
22
|
-
--color-secondary: hsl(228 24% 96%);
|
|
23
|
-
--color-secondary-foreground: hsl(230 24% 14%);
|
|
24
|
-
--color-muted-foreground: hsl(228 8% 46%);
|
|
25
|
-
--color-border: hsl(220 14% 90%);
|
|
26
|
-
|
|
27
|
-
--radius-lg: 12px;
|
|
28
|
-
--radius-md: 8px;
|
|
29
|
-
--radius-sm: 6px;
|
|
30
|
-
|
|
31
|
-
--font-sans: 'Wix Madefor Text', system-ui, sans-serif;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@layer base {
|
|
35
|
-
body {
|
|
36
|
-
background-color: var(--color-background);
|
|
37
|
-
color: var(--color-foreground);
|
|
38
|
-
font-family: var(--font-sans);
|
|
39
|
-
-webkit-font-smoothing: antialiased;
|
|
40
|
-
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@layer utilities {
|
|
45
|
-
.eyebrow {
|
|
46
|
-
font-size: 0.8125rem;
|
|
47
|
-
font-weight: 600;
|
|
48
|
-
letter-spacing: 0.1em;
|
|
49
|
-
text-transform: uppercase;
|
|
50
|
-
color: var(--color-muted-foreground);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Wix connection config — written by the skill's deploy step (install/deploy.mjs).
|
|
2
|
-
//
|
|
3
|
-
// WIX_CLIENT_ID = null → ambient auth (a Wix-managed Astro project: `@wix/astro` authenticates
|
|
4
|
-
// every SDK call automatically; there is no client and nothing to set).
|
|
5
|
-
// WIX_CLIENT_ID = "..." → manual visitor client (any other React setup): the public OAuth client id.
|
|
6
|
-
// It is NOT a secret — it only mints anonymous visitor tokens — so
|
|
7
|
-
// hardcoding and committing it is fine. On a Wix-managed non-Astro project
|
|
8
|
-
// it equals the `appId` in wix.config.json.
|
|
9
|
-
export const WIX_CLIENT_ID: string | null = null;
|
|
10
|
-
|
|
11
|
-
// The Members vertical uses an explicit OAuthStrategy client only to drive the
|
|
12
|
-
// custom credential form. In managed Astro it writes the resulting member
|
|
13
|
-
// tokens into Astro's wixSession cookie, so subsequent ambient SDK calls use
|
|
14
|
-
// that same member identity.
|
|
15
|
-
export const WIX_MEMBERS_CLIENT_ID: string | null = null;
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// Wix media resolution — define once, use on EVERY image render path. Copy as-is.
|
|
2
|
-
//
|
|
3
|
-
// SDK media fields come back either as an already-absolute https URL, or as a
|
|
4
|
-
// `wix:image://v1/<hash>/<file>#originWidth=…` identifier that a browser cannot load
|
|
5
|
-
// (ERR_UNKNOWN_URL_SCHEME). The wix:image:// form must go through the SDK media module;
|
|
6
|
-
// never hand-build a static.wixstatic.com URL (wrong format → 403).
|
|
7
|
-
// docs: https://dev.wix.com/docs/sdk/core-modules/sdk/media.md
|
|
8
|
-
import { media } from "@wix/sdk";
|
|
9
|
-
|
|
10
|
-
type MediaLike =
|
|
11
|
-
| string
|
|
12
|
-
| null
|
|
13
|
-
| undefined
|
|
14
|
-
| { image?: string | null; url?: string | null };
|
|
15
|
-
|
|
16
|
-
/** Resolve any Wix media value to a browser-loadable URL ("" when absent). */
|
|
17
|
-
export function imgSrc(value: MediaLike, width = 600, height = 600): string {
|
|
18
|
-
const v =
|
|
19
|
-
typeof value === "object" && value !== null
|
|
20
|
-
? (value.image ?? value.url ?? "")
|
|
21
|
-
: (value ?? "");
|
|
22
|
-
if (!v) return "";
|
|
23
|
-
if (typeof v === "string" && v.startsWith("wix:image://")) {
|
|
24
|
-
return media.getScaledToFillImageUrl(v, width, height, {});
|
|
25
|
-
}
|
|
26
|
-
if (typeof v !== "string") return "";
|
|
27
|
-
// An absolute Wix media URL (bare, or already carrying a /v1/fill/ segment at some other size):
|
|
28
|
-
// re-issue it through the 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 `https://static.wixstatic.com/media/${m[1]}/v1/fill/w_${width},h_${height},al_c,q_90/${m[1]}`;
|
|
31
|
-
return v;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Responsive candidates for `srcset`: the same image at several widths through Wix's scaler, so a
|
|
36
|
-
* card never downloads a hero-sized file. Pair with `sizes`:
|
|
37
|
-
* <img src={imgSrc(m, 640, 640)} srcSet={imgSrcSet(m)} sizes="(min-width: 1024px) 25vw, 50vw"
|
|
38
|
-
* width={640} height={640} loading="lazy" alt={…} />
|
|
39
|
-
* Accepts every form an image reaches you in: a raw `wix:image://` id, an ALREADY-RESOLVED Wix URL
|
|
40
|
-
* (what the DTOs carry — `imageUrl`, `gallery[]`; its `/v1/fill/w_…,h_…` segment is rewritten per
|
|
41
|
-
* width), or any other https URL (returned as the single candidate). `ratio` is height/width
|
|
42
|
-
* (1 = square). "" only when there is no image at all — still set `src` as well.
|
|
43
|
-
*/
|
|
44
|
-
export function imgSrcSet(value: MediaLike, widths: number[] = [320, 480, 640, 960], ratio = 1): string {
|
|
45
|
-
const raw = typeof value === "object" && value !== null ? (value.image ?? value.url ?? "") : (value ?? "");
|
|
46
|
-
if (typeof raw !== "string" || !raw) return "";
|
|
47
|
-
if (raw.startsWith("wix:image://")) {
|
|
48
|
-
return widths.map((w) => `${imgSrc(value, w, Math.round(w * ratio))} ${w}w`).join(", ");
|
|
49
|
-
}
|
|
50
|
-
// A resolved Wix URL: …/v1/fill/w_800,h_800,al_c,… — swap the size for each width.
|
|
51
|
-
const FILL = /\/v1\/fill\/w_\d+,h_\d+/;
|
|
52
|
-
if (/static\.wixstatic\.com\//.test(raw) && FILL.test(raw)) {
|
|
53
|
-
return widths.map((w) => `${raw.replace(FILL, `/v1/fill/w_${w},h_${Math.round(w * ratio)}`)} ${w}w`).join(", ");
|
|
54
|
-
}
|
|
55
|
-
return raw; // one candidate, never an empty srcset for a real image
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Everything an <img> needs for one Wix image, so a tile can never ship `srcSet` without `src`:
|
|
60
|
-
* <img {...imgAttrs(p.imageUrl, "(min-width: 1024px) 25vw, 50vw")} alt={p.name} />
|
|
61
|
-
* `sizes` is the width the image renders at (a CSS length or media-query list); `ratio` is
|
|
62
|
-
* height/width. Returns an empty object when there is no image — render your placeholder then.
|
|
63
|
-
*/
|
|
64
|
-
export function imgAttrs(value: MediaLike, sizes: string, ratio = 1): { src: string; srcSet: string; sizes: string; loading: "lazy"; decoding: "async" } | Record<string, never> {
|
|
65
|
-
const src = imgSrc(value, 640, Math.round(640 * ratio));
|
|
66
|
-
if (!src) return {};
|
|
67
|
-
return { src, srcSet: imgSrcSet(value, undefined, ratio), sizes, loading: "lazy", decoding: "async" };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The identity of a media value BEFORE scaling — de-duplicate galleries on this, never on a
|
|
72
|
-
* resolved URL (two scaled URLs of one photo differ in their size parameters).
|
|
73
|
-
*/
|
|
74
|
-
export function mediaKey(value: MediaLike): string {
|
|
75
|
-
const v = typeof value === "object" && value !== null ? (value.image ?? value.url ?? "") : (value ?? "");
|
|
76
|
-
if (!v) return "";
|
|
77
|
-
// The file id, whichever form the value takes — a raw id and a resolved URL of one photo share it.
|
|
78
|
-
if (v.startsWith("wix:image://")) return v.slice("wix:image://v1/".length).split("/")[0].split("#")[0];
|
|
79
|
-
const m = v.match(/^https:\/\/static\.wixstatic\.com\/media\/([^/?#]+)/);
|
|
80
|
-
return m ? m[1] : v;
|
|
81
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// Money formatting for API amounts that carry no formatted string. Copy as-is.
|
|
2
|
-
//
|
|
3
|
-
// Catalog prices come with a ready `formattedAmount` — use that directly. But eCom Cart V2
|
|
4
|
-
// amounts are ConvertedMoney `{ amount, convertedAmount }` with NO formatted string, and the
|
|
5
|
-
// currency lives on the cart, not on the money object. Never hardcode "$" or assume USD.
|
|
6
|
-
export interface ConvertedMoneyLike {
|
|
7
|
-
amount?: string | null;
|
|
8
|
-
convertedAmount?: string | null;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** Format a ConvertedMoney in the given currency, using the visitor's locale. */
|
|
12
|
-
export function formatMoney(
|
|
13
|
-
money: ConvertedMoneyLike | null | undefined,
|
|
14
|
-
currencyCode: string | null | undefined,
|
|
15
|
-
): string {
|
|
16
|
-
const value = money?.convertedAmount ?? money?.amount;
|
|
17
|
-
if (value == null || value === "") return "";
|
|
18
|
-
const currency = currencyCode || "USD";
|
|
19
|
-
try {
|
|
20
|
-
return new Intl.NumberFormat(undefined, { style: "currency", currency }).format(Number(value));
|
|
21
|
-
} catch {
|
|
22
|
-
return `${value} ${currency}`;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// The one auth seam for every Wix SDK call in this app. Copy as-is; do not rewrite.
|
|
2
|
-
//
|
|
3
|
-
// Two modes, switched by WIX_CLIENT_ID in ./config:
|
|
4
|
-
// null (ambient) — a Wix-managed Astro project: `@wix/astro` authenticates raw SDK module
|
|
5
|
-
// calls automatically, server-side AND in client islands. `wixModule()`
|
|
6
|
-
// returns the module untouched.
|
|
7
|
-
// string (manual) — any other React setup (Vite SPA, non-Astro): one shared client is built
|
|
8
|
-
// with OAuthStrategy, and `wixModule()` returns the module bound to it.
|
|
9
|
-
// The strategy self-manages visitor tokens on every call (mints on first
|
|
10
|
-
// use, renews on expiry) and persists them through the storage below.
|
|
11
|
-
//
|
|
12
|
-
// The visitor token IS the identity of the current cart / member session, so in manual mode
|
|
13
|
-
// tokens persist to localStorage — never re-minted per load (a fresh anonymous mint is a NEW
|
|
14
|
-
// visitor and silently empties the cart).
|
|
15
|
-
// docs: https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md
|
|
16
|
-
// docs: https://dev.wix.com/docs/go-headless/wix-managed-headless/authentication/about-the-astro-integration.md
|
|
17
|
-
import { createClient, OAuthStrategy, EMPTY_TOKENS } from "@wix/sdk";
|
|
18
|
-
import { fetchWithAuth as ambientFetch } from "@wix/sdk/context";
|
|
19
|
-
import type { IOAuthStrategy, TokenStorage, Tokens } from "@wix/sdk";
|
|
20
|
-
import { WIX_CLIENT_ID } from "./config";
|
|
21
|
-
|
|
22
|
-
const STORAGE_KEY = `wix-session-${WIX_CLIENT_ID ?? "ambient"}`;
|
|
23
|
-
|
|
24
|
-
function browserTokenStorage(): TokenStorage {
|
|
25
|
-
return {
|
|
26
|
-
getTokens(): Tokens {
|
|
27
|
-
if (typeof window !== "undefined") {
|
|
28
|
-
try {
|
|
29
|
-
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
30
|
-
if (raw) return JSON.parse(raw) as Tokens;
|
|
31
|
-
} catch {
|
|
32
|
-
/* disabled/corrupt storage — fall through to empty */
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return EMPTY_TOKENS;
|
|
36
|
-
},
|
|
37
|
-
setTokens(tokens: Tokens): void {
|
|
38
|
-
if (typeof window === "undefined") return;
|
|
39
|
-
try {
|
|
40
|
-
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(tokens));
|
|
41
|
-
} catch {
|
|
42
|
-
/* storage full/disabled — the session just won't survive a reload */
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const client = WIX_CLIENT_ID
|
|
49
|
-
? createClient({
|
|
50
|
-
auth: OAuthStrategy({
|
|
51
|
-
clientId: WIX_CLIENT_ID,
|
|
52
|
-
tokenStorage: browserTokenStorage(),
|
|
53
|
-
}),
|
|
54
|
-
})
|
|
55
|
-
: null;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Bind an SDK module to this app's auth. Usage (identical in both modes):
|
|
59
|
-
* import { productsV3 } from "@wix/stores";
|
|
60
|
-
* const products = wixModule(productsV3);
|
|
61
|
-
* await products.queryProducts(...)
|
|
62
|
-
*/
|
|
63
|
-
export function wixModule<T>(module: T): T {
|
|
64
|
-
// The cast bridges the SDK's internal Descriptors constraint; the in/out type is identical.
|
|
65
|
-
return client
|
|
66
|
-
? (client.use(module as unknown as Record<string, unknown>) as unknown as T)
|
|
67
|
-
: module;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* An authenticated fetch of a Wix REST endpoint under the SAME auth as the SDK modules (ambient
|
|
72
|
-
* on managed Astro, the shared client elsewhere) — for the few APIs whose generated SDK module is
|
|
73
|
-
* too heavy to bundle (the Forms schema module alone is 15 MB: server-side it pushes a Wix
|
|
74
|
-
* deploy past its size limit, client-side every visitor downloads it). Same visitor identity,
|
|
75
|
-
* same token, no second mint. `path` is the wixapis.com path; returns the raw Response.
|
|
76
|
-
*/
|
|
77
|
-
export function wixFetch(path: string, init?: RequestInit): Promise<Response> {
|
|
78
|
-
const url = path.startsWith("http") ? path : `https://www.wixapis.com${path}`;
|
|
79
|
-
return client ? client.fetchWithAuth(url, init) : ambientFetch(url, init);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* The shared data client's manual-mode auth strategy, or null under ambient auth. The
|
|
84
|
-
* Members vertical deliberately owns a separate explicit client for its custom in-app login;
|
|
85
|
-
* app code reads that session through the members hooks instead.
|
|
86
|
-
*/
|
|
87
|
-
export function wixAuth(): IOAuthStrategy | null {
|
|
88
|
-
return client ? client.auth : null;
|
|
89
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// Safe browser half of the optional Media Upload capability.
|
|
2
|
-
// The browser supplies bytes only. It cannot choose a destination or elevate a Wix call:
|
|
3
|
-
// the named policy is enforced by /api/wix/media-upload on the server.
|
|
4
|
-
|
|
5
|
-
export type UploadedMedia = {
|
|
6
|
-
id: string;
|
|
7
|
-
url?: string;
|
|
8
|
-
uploadUrl: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type UploadPolicyRequest = {
|
|
12
|
-
policyId: string;
|
|
13
|
-
fileName: string;
|
|
14
|
-
mimeType: string;
|
|
15
|
-
sizeInBytes: number;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export async function uploadMedia(policyId: string, file: File | Blob, fileName?: string): Promise<UploadedMedia> {
|
|
19
|
-
const mimeType = file.type;
|
|
20
|
-
const request: UploadPolicyRequest = {
|
|
21
|
-
policyId,
|
|
22
|
-
fileName: fileName ?? (file instanceof File ? file.name : "upload"),
|
|
23
|
-
mimeType,
|
|
24
|
-
sizeInBytes: file.size,
|
|
25
|
-
};
|
|
26
|
-
const ticket = await fetch("/api/wix/media-upload", {
|
|
27
|
-
method: "POST",
|
|
28
|
-
headers: { "Content-Type": "application/json" },
|
|
29
|
-
body: JSON.stringify(request),
|
|
30
|
-
});
|
|
31
|
-
if (!ticket.ok) throw new Error(`Upload could not be authorized (${ticket.status})`);
|
|
32
|
-
const { uploadUrl } = (await ticket.json()) as UploadedMedia;
|
|
33
|
-
|
|
34
|
-
const uploaded = await fetch(uploadUrl, {
|
|
35
|
-
method: "PUT",
|
|
36
|
-
headers: { "Content-Type": mimeType },
|
|
37
|
-
body: file,
|
|
38
|
-
});
|
|
39
|
-
const payload = (await uploaded.json().catch(() => null)) as
|
|
40
|
-
| { file?: { id?: string; url?: string }; id?: string; url?: string }
|
|
41
|
-
| null;
|
|
42
|
-
const media = payload?.file ?? payload;
|
|
43
|
-
if (!uploaded.ok || !media?.id) throw new Error(`Upload failed (${uploaded.status})`);
|
|
44
|
-
|
|
45
|
-
return { id: media.id, url: media.url, uploadUrl };
|
|
46
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { APIRoute } from "astro";
|
|
2
|
-
import { auth } from "@wix/essentials";
|
|
3
|
-
import { files } from "@wix/media";
|
|
4
|
-
import { mediaUploadPolicies } from "../../../wix/media-upload/policies.generated";
|
|
5
|
-
|
|
6
|
-
const elevatedGenerateUploadUrl = auth.elevate(files.generateFileUploadUrl);
|
|
7
|
-
|
|
8
|
-
type UploadRequest = {
|
|
9
|
-
policyId?: unknown;
|
|
10
|
-
fileName?: unknown;
|
|
11
|
-
mimeType?: unknown;
|
|
12
|
-
sizeInBytes?: unknown;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const json = (body: unknown, status = 200) =>
|
|
16
|
-
new Response(JSON.stringify(body), { status, headers: { "Content-Type": "application/json" } });
|
|
17
|
-
|
|
18
|
-
export const POST: APIRoute = async ({ request }) => {
|
|
19
|
-
let body: UploadRequest;
|
|
20
|
-
try {
|
|
21
|
-
body = (await request.json()) as UploadRequest;
|
|
22
|
-
} catch {
|
|
23
|
-
return json({ error: "Expected JSON" }, 400);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
typeof body.policyId !== "string" ||
|
|
28
|
-
typeof body.fileName !== "string" ||
|
|
29
|
-
typeof body.mimeType !== "string" ||
|
|
30
|
-
typeof body.sizeInBytes !== "number" ||
|
|
31
|
-
!Number.isSafeInteger(body.sizeInBytes)
|
|
32
|
-
) {
|
|
33
|
-
return json({ error: "Invalid upload request" }, 400);
|
|
34
|
-
}
|
|
35
|
-
const policy = mediaUploadPolicies.find((candidate) => candidate.id === body.policyId);
|
|
36
|
-
if (!policy) return json({ error: "Unknown upload policy" }, 404);
|
|
37
|
-
if (!policy.accept.includes(body.mimeType as never)) return json({ error: "File type is not allowed" }, 415);
|
|
38
|
-
if (body.sizeInBytes < 1 || body.sizeInBytes > policy.maxBytes) return json({ error: "File exceeds this policy's size limit" }, 413);
|
|
39
|
-
|
|
40
|
-
// Do not accept a folder id, labels, privacy setting, or any other destination choice from
|
|
41
|
-
// the browser. Add those as fixed policy fields only after the product actually needs them.
|
|
42
|
-
const result = await elevatedGenerateUploadUrl(body.mimeType, {
|
|
43
|
-
fileName: body.fileName.slice(0, 255),
|
|
44
|
-
});
|
|
45
|
-
return json({ uploadUrl: result.uploadUrl });
|
|
46
|
-
};
|
|
@@ -1,155 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
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
|
-
}
|