@wix/agent-skills 1.20.1 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +71 -113
- package/skills/wix-app/references/APP_TOOLS.md +2 -1
- package/skills/wix-app/references/BACKEND_EVENT.md +3 -3
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +41 -152
- package/skills/wix-app/references/DASHBOARD_MODAL.md +4 -4
- 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 +44 -0
- package/skills/wix-app/references/SITE_PLUGIN.md +36 -190
- package/skills/wix-app/references/app-tools/TOOLS.md +3 -1
- package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +21 -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/ECOM_NAVIGATION.md +17 -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/dashboard-plugin/SLOTS.md +4 -18
- 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-app/references/site-plugin/EXAMPLES.md +1 -1
- package/skills/wix-headless-fast/SKILL.md +144 -221
- package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
- package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +15 -15
- package/skills/wix-headless-fast/guides/existing-site.md +76 -0
- package/skills/wix-headless-fast/guides/reference-mode.md +97 -0
- package/skills/wix-headless-fast/install/AGENTS.md +35 -0
- package/skills/wix-headless-fast/install/agents-md.mjs +39 -0
- package/skills/wix-headless-fast/install/attach.mjs +161 -86
- package/skills/wix-headless-fast/install/deploy.mjs +21 -60
- package/skills/wix-headless-fast/install/lock.mjs +55 -0
- package/skills/wix-headless-fast/install/setup.mjs +259 -0
- package/skills/wix-headless-fast/install/templates.mjs +168 -0
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-coupon.md +10 -19
- package/skills/wix-manage/references/events/create-wix-event.md +5 -1
- 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-headless-fast/install/fast-path.mjs +0 -181
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -301
- 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/seed-blog.mjs +0 -287
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -275
- 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/seed-bookings.mjs +0 -302
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -353
- 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/seed-cms.mjs +0 -324
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -305
- 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/seed-events.mjs +0 -276
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -338
- 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/seed-forms.mjs +0 -327
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -314
- 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/seed-members.mjs +0 -94
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -313
- 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/seed-portfolio.mjs +0 -258
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -294
- 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/seed-pricing-plans.mjs +0 -279
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -358
- 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/seed-restaurants.mjs +0 -479
- 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/storefront/INSTRUCTIONS.md +0 -608
- 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 -309
- 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 -167
- 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 -124
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -525
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
// Availability, the booking form, and the createBooking → Cart V2 → checkout-or-place sequence over
|
|
2
|
-
// REST — the twin of app/wix/bookings/booking.ts. Same exports, same DTOs; every body comes from
|
|
3
|
-
// booking-core (the SAME file the SDK transport uses, deployed flat next to this one), so this file
|
|
4
|
-
// is only the transport: literal paths, one fetch per step. Failures are loud: a taken slot, a
|
|
5
|
-
// refused cart, a checkout that won't start all throw — surface the message to the visitor.
|
|
6
|
-
// All calls run with the visitor token: the booking and its cart are the token's (see ./client).
|
|
7
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/time-slots/time-slots-v2/list-availability-time-slots.md
|
|
8
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/time-slots/time-slots-v2/list-event-time-slots.md
|
|
9
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/create-booking.md
|
|
10
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/create-cart.md
|
|
11
|
-
// docs: https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md
|
|
12
|
-
// docs: https://dev.wix.com/docs/api-reference/crm/forms/form-schemas/get-form-summary.md
|
|
13
|
-
import { wixRequest } from "./client.js";
|
|
14
|
-
import {
|
|
15
|
-
FALLBACK_FIELDS,
|
|
16
|
-
appointmentSlotsRequest,
|
|
17
|
-
bookingCartRequest,
|
|
18
|
-
bookingIdOf,
|
|
19
|
-
bookingRequest,
|
|
20
|
-
cartIdOf,
|
|
21
|
-
cartTotal,
|
|
22
|
-
checkoutRedirectRequest,
|
|
23
|
-
checkoutRequired,
|
|
24
|
-
classSlotsRequest,
|
|
25
|
-
confirmedResult,
|
|
26
|
-
defaultTimeZone,
|
|
27
|
-
toFormFields,
|
|
28
|
-
toLocalDateString,
|
|
29
|
-
toSlot,
|
|
30
|
-
type Raw,
|
|
31
|
-
type SlotsWindow,
|
|
32
|
-
} from "./booking-core.js";
|
|
33
|
-
import type { BookingFormField, BookingResult, ServiceDetail, Slot } from "./types.js";
|
|
34
|
-
|
|
35
|
-
export { toLocalDateString };
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Bookable slots for a service in [from, from + days) — APPOINTMENT and CLASS use different APIs;
|
|
39
|
-
* this branches for you. Dates are local wall-clock; timeZone defaults to the visitor's.
|
|
40
|
-
* APPOINTMENT: POST /service-availability/v2/time-slots { serviceId, fromLocalDate, toLocalDate, timeZone, bookable, cursorPaging, includeResourceTypeIds, resourceTypes? }
|
|
41
|
-
* CLASS: POST /service-availability/v2/time-slots/event { serviceIds, fromLocalDate, toLocalDate, timeZone, includeNonBookable, eventFilter? }
|
|
42
|
-
*/
|
|
43
|
-
export async function fetchSlots(service: Pick<ServiceDetail, "id" | "type">, window: SlotsWindow = {}): Promise<Slot[]> {
|
|
44
|
-
const res =
|
|
45
|
-
service.type === "CLASS"
|
|
46
|
-
? await wixRequest<Raw>("/service-availability/v2/time-slots/event", { body: classSlotsRequest(service.id, window) })
|
|
47
|
-
: await wixRequest<Raw>("/service-availability/v2/time-slots", { body: appointmentSlotsRequest(service.id, window) });
|
|
48
|
-
return ((res?.timeSlots ?? []) as Raw[]).map(toSlot);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* The service's booking-form fields, flat and render-ready (values keyed by `target`). ALWAYS a
|
|
53
|
-
* non-empty list — contact basics when the schema is missing/unusable — so the form renders
|
|
54
|
-
* unconditionally. GET /form-schema-service/v4/forms/{formId}/summary (labels, types) and
|
|
55
|
-
* GET /form-schema-service/v4/forms/{formId} (which fields are required — the summary doesn't say).
|
|
56
|
-
*/
|
|
57
|
-
export async function fetchBookingForm(formId: string | null): Promise<BookingFormField[]> {
|
|
58
|
-
if (!formId) return FALLBACK_FIELDS;
|
|
59
|
-
try {
|
|
60
|
-
const id = encodeURIComponent(formId);
|
|
61
|
-
const [res, form] = await Promise.all([
|
|
62
|
-
wixRequest<Raw>(`/form-schema-service/v4/forms/${id}/summary`, { method: "GET" }),
|
|
63
|
-
wixRequest<Raw>(`/form-schema-service/v4/forms/${id}`, { method: "GET" }).catch(() => null),
|
|
64
|
-
]);
|
|
65
|
-
return toFormFields(res?.formSummary, form?.form);
|
|
66
|
-
} catch {
|
|
67
|
-
return FALLBACK_FIELDS;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Book a slot: createBooking → createCart (holds the seat) → calculateCart → hosted checkout (paid)
|
|
73
|
-
* or placeOrder (free / pay-in-person). Call from the browser. `formValues` is the object your
|
|
74
|
-
* inputs wrote, keyed by field `target` — passed as the formSubmission DIRECTLY. Throws with the
|
|
75
|
-
* refusal (slot taken, invalid form) — surface it, don't swallow it. `origin` is the site's real
|
|
76
|
-
* https origin as registered on the OAuth app's allowed domains (browser: window.location.origin).
|
|
77
|
-
* POST /bookings/v2/bookings { booking, formSubmission }
|
|
78
|
-
* POST /ecom/v2/carts { catalogItems: [{ quantity: 1, catalogReference: { catalogItemId: <bookingId>, appId } }], cart: { source: { channelType: "WEB" } } }
|
|
79
|
-
* POST /ecom/v2/carts/{cartId}/calculate {}
|
|
80
|
-
* POST /headless/v1/redirect-session { ecomCheckout: { checkoutId: <cartId> }, callbacks: { postFlowUrl } }
|
|
81
|
-
* POST /ecom/v2/carts/{cartId}/place-order {}
|
|
82
|
-
*/
|
|
83
|
-
export async function bookService(
|
|
84
|
-
service: ServiceDetail,
|
|
85
|
-
slot: Slot,
|
|
86
|
-
formValues: Record<string, unknown>,
|
|
87
|
-
{
|
|
88
|
-
staffId,
|
|
89
|
-
timeZone = defaultTimeZone(),
|
|
90
|
-
origin = typeof window !== "undefined" ? window.location.origin : "",
|
|
91
|
-
}: { staffId?: string; timeZone?: string; origin?: string } = {},
|
|
92
|
-
): Promise<BookingResult> {
|
|
93
|
-
const created = await wixRequest<Raw>("/bookings/v2/bookings", {
|
|
94
|
-
body: { booking: bookingRequest(service, slot, { staffId, timeZone, idKey: "id" }), formSubmission: formValues },
|
|
95
|
-
});
|
|
96
|
-
const bookingId = bookingIdOf(created);
|
|
97
|
-
if (!bookingId) throw new Error("The booking couldn't be created — the slot may have just been taken.");
|
|
98
|
-
|
|
99
|
-
const newCart = await wixRequest<Raw>("/ecom/v2/carts", { body: bookingCartRequest(bookingId) });
|
|
100
|
-
const cartId = cartIdOf(newCart);
|
|
101
|
-
if (!cartId) throw new Error("The booking couldn't be reserved — please try again.");
|
|
102
|
-
|
|
103
|
-
const calc = await wixRequest<Raw>(`/ecom/v2/carts/${cartId}/calculate`, { body: {} });
|
|
104
|
-
if (checkoutRequired(service, cartTotal(calc))) {
|
|
105
|
-
const session = await wixRequest<Raw>("/headless/v1/redirect-session", { body: checkoutRedirectRequest(cartId, origin) });
|
|
106
|
-
const url = session?.redirectSession?.fullUrl;
|
|
107
|
-
if (!url) throw new Error("Checkout couldn't start — please try again.");
|
|
108
|
-
return { kind: "redirect", url };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const order = await wixRequest<Raw>(`/ecom/v2/carts/${cartId}/place-order`, { body: {} });
|
|
112
|
-
return confirmedResult(bookingId, order);
|
|
113
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// Service reads over REST — the twin of app/wix/bookings/services.ts. Same exports, same DTOs; the
|
|
2
|
-
// rules and mappers come from services-core (the SAME file the SDK transport uses, deployed flat
|
|
3
|
-
// next to this one by deploy.mjs --stack static), so this file is only the transport: one fetch with
|
|
4
|
-
// a literal body per function. Every call here is safe from a browser with a visitor token.
|
|
5
|
-
// Porting: keep the paths, keep the bodies, port the core once.
|
|
6
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/query-services.md
|
|
7
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/query-categories.md
|
|
8
|
-
import { wixRequest } from "./client.js";
|
|
9
|
-
import { imgSrc } from "./media.js";
|
|
10
|
-
import {
|
|
11
|
-
BOOKINGS_APP_ID,
|
|
12
|
-
SERVICES_CONDITIONAL_FIELDS,
|
|
13
|
-
STAFF_RESOURCE_TYPE_ID,
|
|
14
|
-
isVisible,
|
|
15
|
-
servicesFilter,
|
|
16
|
-
toCategory,
|
|
17
|
-
toDetail,
|
|
18
|
-
toSummary,
|
|
19
|
-
type Raw,
|
|
20
|
-
} from "./services-core.js";
|
|
21
|
-
import type { BookingCategory, ServiceDetail, ServiceSummary } from "./types.js";
|
|
22
|
-
|
|
23
|
-
export { BOOKINGS_APP_ID, STAFF_RESOURCE_TYPE_ID };
|
|
24
|
-
|
|
25
|
-
// POST /bookings/v2/services/query { query: { filter, paging: { limit } }, conditionalFields }
|
|
26
|
-
async function queryServices(slug: string | undefined, limit: number): Promise<Raw[]> {
|
|
27
|
-
const res = await wixRequest<Raw>("/bookings/v2/services/query", {
|
|
28
|
-
body: { query: { filter: servicesFilter(slug), paging: { limit } }, conditionalFields: SERVICES_CONDITIONAL_FIELDS },
|
|
29
|
-
});
|
|
30
|
-
return (res?.services ?? []) as Raw[];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** List bookable services (hidden ones filtered), mapped to grid-ready DTOs. */
|
|
34
|
-
export async function fetchServices({ limit = 100 } = {}): Promise<ServiceSummary[]> {
|
|
35
|
-
return (await queryServices(undefined, limit)).filter(isVisible).map((s) => toSummary(s, imgSrc));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** One service by its URL slug (mainSlug.name) — a query with the slug in the filter. Null when not found. */
|
|
39
|
-
export async function fetchServiceBySlug(slug: string): Promise<ServiceDetail | null> {
|
|
40
|
-
const raw = (await queryServices(slug, 1))[0];
|
|
41
|
-
return raw ? toDetail(raw, imgSrc) : null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Service categories for a filter bar — non-fatal (empty array on failure).
|
|
46
|
-
* POST /bookings/v2/categories/query { query: {} }
|
|
47
|
-
*/
|
|
48
|
-
export async function fetchBookingCategories(): Promise<BookingCategory[]> {
|
|
49
|
-
try {
|
|
50
|
-
const res = await wixRequest<Raw>("/bookings/v2/categories/query", { body: { query: {} } });
|
|
51
|
-
return ((res?.categories ?? []) as Raw[]).map(toCategory).filter((c) => c.id);
|
|
52
|
-
} catch {
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# Bookings — seeding
|
|
2
|
-
|
|
3
|
-
Seed by **running `seed-bookings.mjs` with a plan file** — don't hand-write the REST calls.
|
|
4
|
-
The script mints its own site token via the Wix CLI (logged-in session + `wix.config.json`
|
|
5
|
-
required), installs the Bookings app if needed, resolves a staff resource (polling — a fresh
|
|
6
|
-
install provisions the owner asynchronously), and creates everything in the right order.
|
|
7
|
-
|
|
8
|
-
```bash
|
|
9
|
-
# from the project root (where wix.config.json lives):
|
|
10
|
-
node <SKILL_ROOT>/references/bookings/seed/seed-bookings.mjs plan.json
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
`plan.json` is plain data — write it from the brief. **Default to 3 services** (the seed
|
|
14
|
-
shows the shape; the owner adds the rest in the dashboard) and make them exercise the UI:
|
|
15
|
-
mix APPOINTMENT and CLASS when it fits the business, include ≥1 free/pay-in-person service,
|
|
16
|
-
and give every service an image — the default is an `imagePrompt` (AI-generated, ~1 Wix AI
|
|
17
|
-
credit per image, account-billed): brand-contextual — subject, aesthetic/mood, palette,
|
|
18
|
-
lighting — always ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually supplied use `imagePath` (a file on this
|
|
19
|
-
machine — uploaded to Wix Media) or `imageUrl` (their own hosted URL; verify it with
|
|
20
|
-
`curl -sI` → 200) — never a stock-photo or guessed URL. Images resolve in parallel and never block the seed; a failed
|
|
21
|
-
image leaves that service text-only.
|
|
22
|
-
|
|
23
|
-
```json
|
|
24
|
-
{
|
|
25
|
-
"services": [
|
|
26
|
-
{ "type": "APPOINTMENT", "name": "Deep Tissue Massage", "tagLine": "60 minutes of relief",
|
|
27
|
-
"description": "…", "price": 85, "duration": 60, "category": "Massage",
|
|
28
|
-
"imageUrl": "https://…" },
|
|
29
|
-
{ "type": "APPOINTMENT", "name": "Intro Consultation", "description": "…", "free": true,
|
|
30
|
-
"duration": 30, "category": "Massage", "imageUrl": "https://…" },
|
|
31
|
-
{ "type": "CLASS", "name": "Morning Yoga", "description": "…", "price": 20, "capacity": 12,
|
|
32
|
-
"category": "Classes", "imageUrl": "https://…",
|
|
33
|
-
"sessions": [
|
|
34
|
-
{ "start": "2026-09-01T09:00:00", "end": "2026-09-01T10:00:00" },
|
|
35
|
-
{ "start": "2026-09-03T09:00:00", "end": "2026-09-03T10:00:00" }
|
|
36
|
-
] }
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
- `type` — `APPOINTMENT` (visitor picks a free slot; needs `duration` in minutes) or `CLASS`
|
|
42
|
-
(fixed `sessions` you schedule here — **future local wall-clock** `YYYY-MM-DDThh:mm:ss`, no Z;
|
|
43
|
-
a CLASS without sessions shows no bookable times).
|
|
44
|
-
- `price` — a number; omit or `free: true` → a no-fee, pay-in-person service (books without
|
|
45
|
-
checkout). The site currency wins over `currency`.
|
|
46
|
-
- `category` — a name; created idempotently. Every service gets one (required for live-site
|
|
47
|
-
visibility) — uncategorized services fall into a default "Services" category.
|
|
48
|
-
- Staff: appointments are auto-assigned to the site's default staff resource; the flow books
|
|
49
|
-
with ANY_RESOURCE when the visitor doesn't choose.
|
|
50
|
-
|
|
51
|
-
**Seeding is additive — never delete or overwrite existing content**; ask first if a cleanup
|
|
52
|
-
seems needed.
|
|
53
|
-
|
|
54
|
-
## Supplied content
|
|
55
|
-
|
|
56
|
-
The general rules are in `references/shared/SUPPLIED-CONTENT.md`. For bookings, each service the
|
|
57
|
-
user lists is one entry. Its name becomes `name` and its length in minutes becomes `duration`. Its
|
|
58
|
-
price becomes `price`; a service marked free, or with no price, gets `"free": true`. A group activity
|
|
59
|
-
with a capacity or fixed times becomes a `CLASS` with `capacity` and one `sessions` entry per listed
|
|
60
|
-
time; everything else is an `APPOINTMENT`. A category or group becomes `category`. Their photo
|
|
61
|
-
becomes `imageUrl`. A service with no duration is a question for the user. Staff members and
|
|
62
|
-
opening hours are not seeded — say so; the owner sets them in the dashboard.
|
|
63
|
-
|
|
64
|
-
## Escape hatch — individual functions
|
|
65
|
-
`setupBookings` composes exported steps — `installBookingsApp`, `queryStaffWithRetry`,
|
|
66
|
-
`createCategories`, `createServices`, `scheduleClassSessions`, `importImage`,
|
|
67
|
-
`attachServiceImage`, plus `makeCtx()` — import them only for a partial re-seed.
|
|
68
|
-
|
|
69
|
-
## Reference
|
|
70
|
-
Unexpected shape or an uncovered operation → read the live Wix API reference; the
|
|
71
|
-
authoritative source recipe is `wix-headless/references/inline-recipes/setup-bookings.md`.
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
// Bookings seed — a BUILD-TIME script, never shipped in the app. Run from the project root
|
|
2
|
-
// (where wix.config.json lives) with a plan file:
|
|
3
|
-
//
|
|
4
|
-
// node <SKILL_ROOT>/references/bookings/seed/seed-bookings.mjs plan.json
|
|
5
|
-
//
|
|
6
|
-
// It mints its own site token via the Wix CLI, installs the Wix Bookings app if needed,
|
|
7
|
-
// resolves a staff resource (polling — a fresh install provisions the owner async), creates
|
|
8
|
-
// categories (idempotent by name) and services (bulk; APPOINTMENT + CLASS mixed), schedules
|
|
9
|
-
// CLASS sessions, and imports+attaches images. Prints a JSON result to stdout.
|
|
10
|
-
//
|
|
11
|
-
// Plan shape (see SEED.md):
|
|
12
|
-
// { "services": [{ "type": "APPOINTMENT"|"CLASS", "name", "description", "tagLine"?,
|
|
13
|
-
// "price"?, "free"?, "duration"? (APPOINTMENT, minutes), "capacity"?,
|
|
14
|
-
// "category"? (name), "imageUrl"? | "imagePrompt"?,
|
|
15
|
-
// "sessions"?: [{ "start", "end", "capacity"? }] }] } // CLASS only; local "YYYY-MM-DDThh:mm:ss"
|
|
16
|
-
//
|
|
17
|
-
// Seeding is ADDITIVE — never deletes or overwrites existing content. Unexpected shapes →
|
|
18
|
-
// read the live API reference; authoritative source recipe:
|
|
19
|
-
// wix-headless/references/inline-recipes/setup-bookings.md.
|
|
20
|
-
import { execFileSync } from "node:child_process";
|
|
21
|
-
import { readFileSync } from "node:fs";
|
|
22
|
-
import { resolveItemImages } from "../../shared/seed/images.mjs";
|
|
23
|
-
|
|
24
|
-
const API = "https://www.wixapis.com";
|
|
25
|
-
const BOOKINGS_APP_ID = "13d21c63-b5ec-5912-8397-c3a5ddb27a97";
|
|
26
|
-
|
|
27
|
-
export function makeCtx({ cwd = process.cwd() } = {}) {
|
|
28
|
-
const config = JSON.parse(readFileSync(`${cwd}/wix.config.json`, "utf8"));
|
|
29
|
-
const siteId = config.siteId ?? config.projectId;
|
|
30
|
-
if (!siteId) throw new Error("wix.config.json has no siteId — is this a Wix CLI project?");
|
|
31
|
-
const token = execFileSync("npx", ["@wix/cli@latest", "token", "--site", siteId], {
|
|
32
|
-
encoding: "utf8",
|
|
33
|
-
cwd,
|
|
34
|
-
}).trim();
|
|
35
|
-
if (!token) throw new Error("The Wix CLI returned no token — run `npx @wix/cli@latest login` first.");
|
|
36
|
-
return { token, siteId };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function req(ctx, path, { method = "POST", body } = {}) {
|
|
40
|
-
const res = await fetch(API + path, {
|
|
41
|
-
method,
|
|
42
|
-
headers: {
|
|
43
|
-
Authorization: `Bearer ${ctx.token}`,
|
|
44
|
-
"wix-site-id": ctx.siteId,
|
|
45
|
-
"Content-Type": "application/json",
|
|
46
|
-
},
|
|
47
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
48
|
-
});
|
|
49
|
-
const json = await res.json().catch(() => ({}));
|
|
50
|
-
if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
|
|
51
|
-
return json;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
55
|
-
|
|
56
|
-
function slugify(name) {
|
|
57
|
-
return String(name || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// plain service -> flat Services V2 create object. price omitted / free:true -> NO_FEE.
|
|
61
|
-
function buildService(s) {
|
|
62
|
-
const isAppointment = s.type === "APPOINTMENT";
|
|
63
|
-
const free = s.free === true || s.price == null;
|
|
64
|
-
const out = {
|
|
65
|
-
type: s.type,
|
|
66
|
-
name: s.name,
|
|
67
|
-
description: s.description,
|
|
68
|
-
tagLine: s.tagLine,
|
|
69
|
-
defaultCapacity: s.capacity ?? (isAppointment ? 1 : undefined),
|
|
70
|
-
onlineBooking: { enabled: true, requireManualApproval: false, allowMultipleRequests: false },
|
|
71
|
-
payment: free
|
|
72
|
-
? { rateType: "NO_FEE", options: { online: false, inPerson: true } }
|
|
73
|
-
: {
|
|
74
|
-
rateType: "FIXED",
|
|
75
|
-
fixed: { price: { value: String(s.price), currency: s.currency ?? "USD" } },
|
|
76
|
-
options: { online: true, inPerson: false },
|
|
77
|
-
},
|
|
78
|
-
category: { id: s.categoryId }, // mandatory for live-site visibility
|
|
79
|
-
locations: [{ type: "BUSINESS" }], // never OWNER_BUSINESS on the services endpoint
|
|
80
|
-
};
|
|
81
|
-
if (isAppointment) {
|
|
82
|
-
out.schedule = { availabilityConstraints: { sessionDurations: [s.duration ?? 60] } };
|
|
83
|
-
out.staffMemberIds = s.staffMemberIds; // resourceId(s) — non-empty or MISSING_APPOINTMENT_RESOURCES
|
|
84
|
-
}
|
|
85
|
-
return out;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ---- operations ----------------------------------------------------------------------------------
|
|
89
|
-
|
|
90
|
-
// docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
|
|
91
|
-
export async function installBookingsApp(ctx) {
|
|
92
|
-
try {
|
|
93
|
-
await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
|
|
94
|
-
tenant: { tenantType: "SITE", id: ctx.siteId },
|
|
95
|
-
appInstance: { appDefId: BOOKINGS_APP_ID, enabled: true },
|
|
96
|
-
} });
|
|
97
|
-
} catch {
|
|
98
|
-
/* already installed is fine */
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ⚠️ staffMemberIds takes resourceId, NOT the staff id.
|
|
103
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members.md
|
|
104
|
-
export async function queryStaff(ctx) {
|
|
105
|
-
const r = await req(ctx, "/bookings/v1/staff-members/query", {
|
|
106
|
-
body: { query: {}, fields: ["RESOURCE_DETAILS"] },
|
|
107
|
-
});
|
|
108
|
-
return (r.staffMembers ?? []).map((m) => ({ resourceId: m.resourceId, id: m.id, name: m.name }));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// A fresh install provisions the default "Business Owner" resource ASYNC — poll until it lands.
|
|
112
|
-
export async function queryStaffWithRetry(ctx, { tries = 15, delayMs = 2000 } = {}) {
|
|
113
|
-
let lastErr;
|
|
114
|
-
for (let i = 0; i < tries; i++) {
|
|
115
|
-
try {
|
|
116
|
-
const s = await queryStaff(ctx);
|
|
117
|
-
if (s.length) return s;
|
|
118
|
-
} catch (e) {
|
|
119
|
-
lastErr = e;
|
|
120
|
-
}
|
|
121
|
-
if (i < tries - 1) await sleep(delayMs);
|
|
122
|
-
}
|
|
123
|
-
if (lastErr) throw lastErr;
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Every service needs a category.id or it's invisible on the live site. Idempotent by name.
|
|
128
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/query-categories.md
|
|
129
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category.md
|
|
130
|
-
export async function createCategories(ctx, names) {
|
|
131
|
-
const existing = await req(ctx, "/bookings/v2/categories/query", { body: { query: {} } });
|
|
132
|
-
const byName = new Map((existing.categories ?? []).map((c) => [c.name, { id: c.id, name: c.name }]));
|
|
133
|
-
const out = [];
|
|
134
|
-
for (const name of names) {
|
|
135
|
-
let cat = byName.get(name);
|
|
136
|
-
if (!cat) {
|
|
137
|
-
const r = await req(ctx, "/bookings/v2/categories", { body: { category: { name } } });
|
|
138
|
-
cat = { id: r.category?.id, name };
|
|
139
|
-
byName.set(name, cat);
|
|
140
|
-
}
|
|
141
|
-
out.push(cat);
|
|
142
|
-
}
|
|
143
|
-
return out;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Bulk-create services (APPOINTMENT + CLASS mixed). Run AFTER staff + categories.
|
|
147
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services.md
|
|
148
|
-
export async function createServices(ctx, services) {
|
|
149
|
-
const body = { services: services.map(buildService), returnEntity: true };
|
|
150
|
-
const r = await req(ctx, "/bookings/v2/bulk/services/create", { body });
|
|
151
|
-
return (r.results ?? []).map((res, i) => {
|
|
152
|
-
const item = res.item ?? {};
|
|
153
|
-
return {
|
|
154
|
-
id: item.id ?? res.itemMetadata?.id,
|
|
155
|
-
slug: item.mainSlug?.name ?? slugify(item.name ?? services[i]?.name),
|
|
156
|
-
revision: item.revision,
|
|
157
|
-
type: item.type ?? services[i]?.type,
|
|
158
|
-
scheduleId: item.schedule?.id,
|
|
159
|
-
success: res.itemMetadata?.success ?? false,
|
|
160
|
-
error: res.itemMetadata?.error,
|
|
161
|
-
};
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// CLASS only: schedule sessions (bulk Calendar Events V3). start/end are LOCAL wall-clock
|
|
166
|
-
// "YYYY-MM-DDThh:mm:ss" (no Z), today-or-future.
|
|
167
|
-
// docs: https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event.md
|
|
168
|
-
export async function scheduleClassSessions(ctx, sessions) {
|
|
169
|
-
const body = {
|
|
170
|
-
events: sessions.map((s) => ({
|
|
171
|
-
event: {
|
|
172
|
-
scheduleId: s.scheduleId,
|
|
173
|
-
type: "CLASS",
|
|
174
|
-
start: { localDate: s.start },
|
|
175
|
-
end: { localDate: s.end },
|
|
176
|
-
resources: [{ id: s.resourceId, permissionRole: "WRITER" }], // non-empty + WRITER, else UNKNOWN_ROLE
|
|
177
|
-
...(s.capacity != null ? { totalCapacity: s.capacity } : {}),
|
|
178
|
-
},
|
|
179
|
-
})),
|
|
180
|
-
};
|
|
181
|
-
const r = await req(ctx, "/calendar/v3/bulk/events/create", { body });
|
|
182
|
-
return (r.results ?? []).map((res) => ({
|
|
183
|
-
id: res.itemMetadata?.id,
|
|
184
|
-
success: res.itemMetadata?.success ?? false,
|
|
185
|
-
error: res.itemMetadata?.error,
|
|
186
|
-
}));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Bookings binds a service image by Wix Media file ID — an external url must be imported
|
|
190
|
-
// first; a plan `imagePrompt` is generated (Wix AI, 1 credit) then imported. Both live in the
|
|
191
|
-
// shared util (parallel, resilient, never blocks the seed).
|
|
192
|
-
export { importImage } from "../../shared/seed/images.mjs";
|
|
193
|
-
|
|
194
|
-
// Writes under media.mainMedia + media.coverMedia (writing media.image 200s but silently drops).
|
|
195
|
-
// docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/update-service.md
|
|
196
|
-
export async function attachServiceImage(ctx, it) {
|
|
197
|
-
return req(ctx, `/bookings/v2/services/${it.serviceId}`, {
|
|
198
|
-
method: "PATCH",
|
|
199
|
-
body: {
|
|
200
|
-
service: {
|
|
201
|
-
id: it.serviceId,
|
|
202
|
-
revision: it.revision,
|
|
203
|
-
media: { mainMedia: { image: it.image }, coverMedia: { image: it.image } },
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* ONE-CALL seed: install → resolve staff (poll) → categories → services → CLASS sessions →
|
|
211
|
-
* images, ids threaded in memory. The default path.
|
|
212
|
-
*/
|
|
213
|
-
export async function setupBookings(ctx, { services = [], staffResourceId } = {}) {
|
|
214
|
-
await installBookingsApp(ctx);
|
|
215
|
-
|
|
216
|
-
let resourceId = staffResourceId;
|
|
217
|
-
if (!resourceId) {
|
|
218
|
-
const staff = await queryStaffWithRetry(ctx);
|
|
219
|
-
resourceId = staff[0]?.resourceId;
|
|
220
|
-
}
|
|
221
|
-
if (!resourceId) throw new Error("No staff resource resolved — Bookings provisioning may still be in progress; re-run the seed.");
|
|
222
|
-
|
|
223
|
-
const catNames = [...new Set(services.map((s) => s.category).filter(Boolean))];
|
|
224
|
-
const cats = catNames.length ? await createCategories(ctx, catNames) : await createCategories(ctx, ["Services"]);
|
|
225
|
-
const catIdByName = new Map(cats.map((c) => [c.name, c.id]));
|
|
226
|
-
const defaultCatId = cats[0]?.id;
|
|
227
|
-
|
|
228
|
-
const created = await createServices(ctx, services.map((s) => ({
|
|
229
|
-
type: s.type,
|
|
230
|
-
name: s.name,
|
|
231
|
-
description: s.description,
|
|
232
|
-
tagLine: s.tagLine,
|
|
233
|
-
price: s.price,
|
|
234
|
-
currency: s.currency,
|
|
235
|
-
free: s.free,
|
|
236
|
-
duration: s.duration,
|
|
237
|
-
capacity: s.capacity,
|
|
238
|
-
categoryId: (s.category ? catIdByName.get(s.category) : undefined) ?? defaultCatId,
|
|
239
|
-
staffMemberIds: s.staffMemberIds ?? (s.type === "APPOINTMENT" ? [resourceId] : undefined),
|
|
240
|
-
})));
|
|
241
|
-
|
|
242
|
-
const sessions = [];
|
|
243
|
-
created.forEach((c, i) => {
|
|
244
|
-
const plan = services[i];
|
|
245
|
-
if (c.type === "CLASS" && c.scheduleId && Array.isArray(plan?.sessions)) {
|
|
246
|
-
for (const ses of plan.sessions) {
|
|
247
|
-
sessions.push({ scheduleId: c.scheduleId, resourceId, start: ses.start, end: ses.end, capacity: ses.capacity ?? plan.capacity });
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
const scheduled = sessions.length ? await scheduleClassSessions(ctx, sessions) : [];
|
|
252
|
-
|
|
253
|
-
// Pass 2 — images: resolve (import by url / generate by prompt) in one parallel wave, then
|
|
254
|
-
// attach. Failures leave the service text-only; the seed's exit never depends on images.
|
|
255
|
-
const files = await resolveItemImages(ctx, created.map((c, i) => ({
|
|
256
|
-
url: services[i]?.imageUrl,
|
|
257
|
-
path: services[i]?.imagePath,
|
|
258
|
-
prompt: services[i]?.imagePrompt,
|
|
259
|
-
displayName: `${c?.slug || "service"}.png`,
|
|
260
|
-
})));
|
|
261
|
-
let imagesAttached = 0;
|
|
262
|
-
for (let i = 0; i < created.length; i++) {
|
|
263
|
-
if (!files[i] || !created[i]?.id) continue;
|
|
264
|
-
try {
|
|
265
|
-
await attachServiceImage(ctx, {
|
|
266
|
-
serviceId: created[i].id,
|
|
267
|
-
revision: created[i].revision,
|
|
268
|
-
image: { id: files[i].id, url: files[i].url, width: 1024, height: 1024 },
|
|
269
|
-
});
|
|
270
|
-
imagesAttached++;
|
|
271
|
-
} catch {
|
|
272
|
-
/* never block on image failure — the service stays text-only */
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return {
|
|
277
|
-
services: created,
|
|
278
|
-
categories: cats,
|
|
279
|
-
resourceId,
|
|
280
|
-
sessionsScheduled: scheduled.filter((s) => s.success).length,
|
|
281
|
-
imagesAttached,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// ---- CLI entry ----------------------------------------------------------------------------------
|
|
286
|
-
|
|
287
|
-
const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
|
|
288
|
-
if (invokedDirectly) {
|
|
289
|
-
const planPath = process.argv[2];
|
|
290
|
-
if (!planPath) {
|
|
291
|
-
console.error("usage: node seed-bookings.mjs <plan.json> (run from the project root)");
|
|
292
|
-
process.exit(1);
|
|
293
|
-
}
|
|
294
|
-
const plan = JSON.parse(readFileSync(planPath, "utf8"));
|
|
295
|
-
const ctx = makeCtx();
|
|
296
|
-
setupBookings(ctx, plan)
|
|
297
|
-
.then((result) => console.log(JSON.stringify(result, null, 2)))
|
|
298
|
-
.catch((e) => {
|
|
299
|
-
console.error(e.message);
|
|
300
|
-
process.exit(1);
|
|
301
|
-
});
|
|
302
|
-
}
|