@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,36 +1,59 @@
|
|
|
1
|
-
// Attach a NEW headless frontend to an EXISTING Wix site —
|
|
1
|
+
// Attach a NEW headless frontend to an EXISTING Wix site — setup's sibling for a site that already
|
|
2
2
|
// exists (named in the prompt by its id). `init`/`wix create` cannot do this: they always create
|
|
3
3
|
// a site. This script does what they do AFTER creating one — OAuth app, managed hosting, env
|
|
4
4
|
// vars, `wix.config.json` — against the site id given, then scaffolds and deploys like
|
|
5
|
-
//
|
|
5
|
+
// setup.mjs. Nothing on the site is created, changed or deleted; there is no seed step.
|
|
6
6
|
//
|
|
7
|
-
// node <SKILL_ROOT>/install/attach.mjs --site <metaSiteId> --business-name "<Brand>" \
|
|
8
|
-
// --vertical <a>[,<b>…] [--stack astro|react|static] [--
|
|
7
|
+
// node <SKILL_ROOT>/install/attach.mjs [--site <metaSiteId>] --business-name "<Brand>" \
|
|
8
|
+
// --vertical <a>[,<b>…] [--stack astro|react|lib|static] [--hosting wix|self [--origin <url>[,<url>]]] \
|
|
9
|
+
// [--subfolder [--folder-name <name>]]
|
|
9
10
|
//
|
|
11
|
+
// --hosting wix (default): the frontend releases to Wix hosting — the site's app project is
|
|
12
|
+
// created or reused and `wix release` uploads to its *.wix-site-host.com address.
|
|
13
|
+
// self: the frontend is hosted elsewhere (Vercel, a Flask server, …): no app
|
|
14
|
+
// project, no Wix address, no Astro template; the OAuth app, wix.config.json and
|
|
15
|
+
// .env.local are still set up, the code deploys for --stack, and the origins given
|
|
16
|
+
// in --origin go on the OAuth app's redirect allow-list, which is what a Wix-hosted
|
|
17
|
+
// flow (checkout) needs to return to a frontend on another host.
|
|
18
|
+
//
|
|
19
|
+
// --site the site. May be omitted when the folder holds a wix.config.json: then it is
|
|
20
|
+
// the site in that config (what `init` left behind in an empty folder).
|
|
10
21
|
// --business-name the site's name (names the folder, the hosting slug and the app project).
|
|
11
22
|
// --vertical which shipped code deploys (no seed runs — the site owns its content). Both are
|
|
12
23
|
// the caller's decision, read off the site before calling this (SKILL.md step 3).
|
|
13
|
-
// --stack
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
24
|
+
// --stack astro (default) in a folder without a project: copies the first vertical's
|
|
25
|
+
// composed template (templates/<vertical>/project). react|static there: writes wix.config.json
|
|
26
|
+
// and stops — the caller scaffolds (Vite / plain HTML) per SKILL.md. In a folder
|
|
27
|
+
// that holds a project, --stack is required and nothing is scaffolded.
|
|
28
|
+
//
|
|
29
|
+
// The FOLDER decides, on file markers only:
|
|
30
|
+
// - a project (package.json or index.html) AND wix.config.json → refuses: a Wix project with a
|
|
31
|
+
// frontend already; deploy.mjs adds a solution to it.
|
|
32
|
+
// - a project, no config → LINK: the hosting calls, then wix.config.json and .env.local are
|
|
33
|
+
// written into the project as it is, the shipped code deploys for --stack, the install starts.
|
|
34
|
+
// - no project (empty, or only a config for this same site) → the scaffold path above.
|
|
35
|
+
// - a config naming a different site → refuses: never re-point a folder; use --subfolder.
|
|
36
|
+
// The project lives in the CURRENT DIRECTORY — the folder that already holds the installed skills —
|
|
37
|
+
// so it is self-contained. `--subfolder` (opt-in) creates it in a new folder named after the
|
|
38
|
+
// business instead.
|
|
19
39
|
//
|
|
20
40
|
// Emits ONE JSON event per line (attached, scaffolded, deployed, install_started,
|
|
21
41
|
// ready_for_brand_layer, or error). Requires a logged-in Wix CLI (`npx @wix/cli@latest whoami`)
|
|
22
42
|
// whose account owns or co-manages the site.
|
|
23
43
|
import { spawn, spawnSync, execFileSync } from "node:child_process";
|
|
24
|
-
import { cpSync, existsSync, mkdirSync,
|
|
25
|
-
import {
|
|
26
|
-
import { dirname, join, resolve } from "node:path";
|
|
44
|
+
import { cpSync, existsSync, mkdirSync, openSync, readFileSync, writeFileSync } from "node:fs";
|
|
45
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
27
46
|
import { fileURLToPath } from "node:url";
|
|
47
|
+
import { writeAgentsMd } from "./agents-md.mjs";
|
|
48
|
+
import { listVerticals, templatesDir } from "./templates.mjs";
|
|
28
49
|
|
|
29
50
|
const SKILL_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
30
51
|
const MANAGE = "https://manage.wix.com";
|
|
52
|
+
const API = "https://www.wixapis.com";
|
|
31
53
|
const HEADLESS_PROJECT_TYPE_ID = "eb363dea-85a0-4159-9b05-949542be5079";
|
|
32
|
-
|
|
33
|
-
|
|
54
|
+
// The shipped code: the repository's templates/ (a checkout, the cache, or fetched now, in a second).
|
|
55
|
+
let TEMPLATES;
|
|
56
|
+
try { TEMPLATES = templatesDir(); } catch (e) { fail("templates", e.message); }
|
|
34
57
|
|
|
35
58
|
const emit = (event, extra = {}) => console.log(JSON.stringify({ event, ...extra }));
|
|
36
59
|
const fail = (step, detail) => {
|
|
@@ -44,25 +67,46 @@ const flag = (name) => {
|
|
|
44
67
|
const i = argv.indexOf(`--${name}`);
|
|
45
68
|
return i !== -1 && argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : null;
|
|
46
69
|
};
|
|
47
|
-
const
|
|
48
|
-
const
|
|
70
|
+
const stackFlag = flag("stack");
|
|
71
|
+
const hosting0 = flag("hosting") ?? "wix";
|
|
72
|
+
const origins = (flag("origin") ?? "").split(",").map((o) => o.trim().replace(/\/$/, "")).filter(Boolean);
|
|
49
73
|
const subfolder = argv.includes("--subfolder");
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
74
|
+
// ---- the folder ---------------------------------------------------------------------------------
|
|
75
|
+
const cwd = process.cwd();
|
|
76
|
+
const has = (p) => existsSync(join(cwd, p));
|
|
77
|
+
const cwdConfig = has("wix.config.json") ? JSON.parse(readFileSync(join(cwd, "wix.config.json"), "utf8")) : null;
|
|
78
|
+
const hasProject = has("package.json") || has("index.html");
|
|
79
|
+
const siteId = flag("site") ?? cwdConfig?.siteId ?? cwdConfig?.projectId ?? null;
|
|
80
|
+
const stack = stackFlag ?? "astro";
|
|
81
|
+
const knownVerticals = listVerticals(TEMPLATES);
|
|
53
82
|
const verticals = argv
|
|
54
83
|
.flatMap((a, i) => (a === "--vertical" && argv[i + 1] ? argv[i + 1].split(",") : []))
|
|
55
84
|
.map((v) => v.trim())
|
|
56
85
|
.filter(Boolean);
|
|
57
86
|
const businessName = flag("business-name");
|
|
58
87
|
if (!siteId || !/^[0-9a-f-]{36}$/i.test(siteId) || !businessName || !verticals.length) {
|
|
59
|
-
fail("args", `usage: attach.mjs --site <metaSiteId> --business-name "<Brand>" --vertical <${knownVerticals.join("|")}>[,…] [--stack astro|react|static]`);
|
|
88
|
+
fail("args", `usage: attach.mjs [--site <metaSiteId>] --business-name "<Brand>" --vertical <${knownVerticals.join("|")}>[,…] [--stack astro|react|lib|static] (--site may be omitted when wix.config.json is here)`);
|
|
60
89
|
}
|
|
61
90
|
for (const v of verticals) if (!knownVerticals.includes(v)) fail("args", `unknown vertical "${v}" — shipped verticals: ${knownVerticals.join(", ")}`);
|
|
62
|
-
if (!["astro", "react", "static"].includes(stack)) fail("args", `unknown stack "${stack}" — astro, react or static`);
|
|
63
|
-
if (
|
|
64
|
-
|
|
91
|
+
if (!["astro", "react", "lib", "static"].includes(stack)) fail("args", `unknown stack "${stack}" — astro, react, lib or static`);
|
|
92
|
+
if (!["wix", "self"].includes(hosting0)) fail("args", `unknown --hosting "${hosting0}" — wix or self`);
|
|
93
|
+
for (const o of origins) if (!/^https?:\/\/[^/\s]+$/.test(o)) fail("args", `--origin must be a scheme and host such as https://shop.example.com or http://localhost:8000, got "${o}"`);
|
|
94
|
+
if (hosting0 === "self" && stack === "astro" && !hasProject && !stackFlag) {
|
|
95
|
+
fail("args", "--hosting self scaffolds nothing: pass --stack for the frontend you will host (react|lib|static), or attach from inside the project on disk");
|
|
65
96
|
}
|
|
97
|
+
if (!subfolder) {
|
|
98
|
+
if (hasProject && cwdConfig) {
|
|
99
|
+
fail("place", "this folder is already a Wix project with a frontend (wix.config.json and a project): nothing to attach. deploy.mjs <vertical> adds this skill's code or a solution to it; then ONE npm install");
|
|
100
|
+
}
|
|
101
|
+
if (cwdConfig && (cwdConfig.siteId ?? cwdConfig.projectId) !== siteId) {
|
|
102
|
+
fail("place", `this folder is attached to site ${cwdConfig.siteId ?? cwdConfig.projectId}, not ${siteId} — a folder is never re-pointed; attach the other site with --subfolder`);
|
|
103
|
+
}
|
|
104
|
+
if (hasProject && !stackFlag) {
|
|
105
|
+
fail("args", "attaching a project on disk needs --stack astro|react|lib|static — the stack you resolved in SKILL.md step 1 for this project");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const mode = !subfolder && hasProject ? "link" : hosting0 === "self" ? "config-only" : "scaffold";
|
|
109
|
+
emit("folder", { mode, stack, hosting: hosting0, project: hasProject, config: cwdConfig ? "same site" : null });
|
|
66
110
|
|
|
67
111
|
// ---- http ---------------------------------------------------------------------------------------
|
|
68
112
|
const cliToken = (site) => {
|
|
@@ -92,25 +136,27 @@ async function call(base, path, { method = "POST", token, site, body, query } =
|
|
|
92
136
|
}
|
|
93
137
|
|
|
94
138
|
const folderName = flag("folder-name") ?? (businessName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "site");
|
|
95
|
-
const projectDir = subfolder ? resolve(
|
|
139
|
+
const projectDir = subfolder ? resolve(cwd, folderName) : cwd;
|
|
96
140
|
if (subfolder && existsSync(join(projectDir, "wix.config.json"))) fail("args", `${folderName}/ is already a Wix project — pick --folder-name, or run deploy.mjs there`);
|
|
97
141
|
|
|
98
142
|
// ---- 1 · attach: OAuth app + hosting + env, on the manage host with a site token -----------------
|
|
99
143
|
// The same calls `init` makes after it has created a site, in the same order.
|
|
100
144
|
const siteToken = cliToken(siteId);
|
|
101
145
|
const opts = { token: siteToken, site: siteId };
|
|
102
|
-
let appId, appProject, instanceId, secrets, hosting = "created";
|
|
146
|
+
let appId, appProject = null, instanceId, secrets, hosting = hosting0 === "self" ? "self" : "created";
|
|
103
147
|
try {
|
|
104
148
|
const comp = await call(MANAGE, "/_api/companion-apps/v1/companion-apps/get-or-create", { ...opts, body: {} });
|
|
105
149
|
appId = comp.companionApp?.id;
|
|
106
150
|
if (!appId) throw new Error("get-or-create returned no companion app id");
|
|
107
151
|
const slug = folderName;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
152
|
+
if (hosting0 === "wix") {
|
|
153
|
+
try { appProject = (await call(MANAGE, `/_api/wix-code-app-projects/v1/app-projects/${appId}`, { ...opts, method: "GET" })).appProject; } catch { appProject = null; }
|
|
154
|
+
if (appProject) {
|
|
155
|
+
hosting = "reused";
|
|
156
|
+
} else {
|
|
157
|
+
try { await call(MANAGE, `/apps-service/v1/apps/${appId}/set-namespace`, { ...opts, method: "PATCH", body: { appId, appName: businessName, namespace: slug } }); }
|
|
158
|
+
catch (e) { emit("note", { step: "set-namespace", detail: String(e.message).slice(0, 200) }); }
|
|
159
|
+
}
|
|
114
160
|
}
|
|
115
161
|
try {
|
|
116
162
|
const inst = await call(MANAGE, "/apps-installer-service/v1/app-instance/install", { ...opts, body: { tenant: { id: siteId, tenantType: "SITE" }, appInstance: { appDefId: appId, version: "latest" } } });
|
|
@@ -118,9 +164,23 @@ try {
|
|
|
118
164
|
} catch (e) { emit("note", { step: "install", detail: String(e.message).slice(0, 200) }); }
|
|
119
165
|
secrets = (await call(MANAGE, `/apps-service/v1/apps/${appId}`, { ...opts, method: "GET", query: { withSecrets: true } })).app?.appSecrets;
|
|
120
166
|
if (!secrets?.appSecret) throw new Error("app secrets unavailable for this app");
|
|
121
|
-
if (
|
|
167
|
+
if (hosting0 === "self") {
|
|
168
|
+
// No Wix hosting. The one thing a frontend on another host needs from the site: its origins on
|
|
169
|
+
// the OAuth app's redirect allow-list, so checkout and the other Wix-hosted flows can return.
|
|
170
|
+
// The public OAuth Apps API (wix-manage: Manage OAuth Apps), merged with what is already there.
|
|
171
|
+
if (origins.length) {
|
|
172
|
+
const current = (await call(API, `/oauth-app/v1/oauth-apps/${appId}`, { ...opts, method: "GET" })).oAuthApp ?? {};
|
|
173
|
+
const merged = [...new Set([...(current.allowedRedirectDomains ?? []), ...origins])];
|
|
174
|
+
await call(API, `/oauth-app/v1/oauth-apps/${appId}`, { ...opts, method: "PATCH", body: { oAuthApp: { allowedRedirectDomains: merged }, mask: { paths: ["allowedRedirectDomains"] } } });
|
|
175
|
+
emit("origins_allowed", { appId, allowedRedirectDomains: merged });
|
|
176
|
+
} else {
|
|
177
|
+
emit("note", { step: "origins", detail: "no --origin given: add the frontend's origins to the OAuth app's allowedRedirectDomains (wix-manage: Manage OAuth Apps) before the first checkout test" });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (hosting0 === "wix" && !appProject) {
|
|
122
181
|
appProject = (await call(MANAGE, "/_api/wix-code-app-projects/v1/app-projects", { ...opts, body: { appProject: { id: appId, displayName: businessName.slice(0, 50), slug, appProjectTypeId: HEADLESS_PROJECT_TYPE_ID } } })).appProject;
|
|
123
182
|
}
|
|
183
|
+
if (hosting0 === "wix") {
|
|
124
184
|
if (!appProject?.baseUrl) throw new Error("app project has no baseUrl");
|
|
125
185
|
const prod = String(appProject.baseUrl).replace(/\/$/, "");
|
|
126
186
|
const host = new URL(appProject.baseUrl).hostname;
|
|
@@ -146,55 +206,54 @@ try {
|
|
|
146
206
|
await call(MANAGE, `/_api/wix-code-app-environments/v2/bulk/app-projects/${appProject.id}/app-environment-variables/upsert`, { ...opts, body: {
|
|
147
207
|
appProjectId: appProject.id, environment: "system_global", mutability: "STATIC", returnEntity: true, returnAllEnvironment: true, variables,
|
|
148
208
|
} });
|
|
209
|
+
}
|
|
149
210
|
} catch (e) {
|
|
150
211
|
fail("attach", e?.message || e);
|
|
151
212
|
}
|
|
152
|
-
const baseUrl = String(appProject.baseUrl).replace(/\/$/, "");
|
|
153
|
-
|
|
213
|
+
const baseUrl = appProject ? String(appProject.baseUrl).replace(/\/$/, "") : null;
|
|
214
|
+
// Is a frontend serving at that address? The hosting project says nothing about it (init and the
|
|
215
|
+
// provisioning call create one with nothing behind it). The site's release slots do: the release
|
|
216
|
+
// with slug `prod` is production traffic and names the deployment it serves — the same read the
|
|
217
|
+
// headless back office makes for its frontend status. Absent means nothing was ever released.
|
|
218
|
+
// Deployments keep their own addresses, so a replaced one is not lost; prod can be pointed back.
|
|
219
|
+
// A folder that reaches this point is not the one that released (a linked project never runs
|
|
220
|
+
// attach), so a `prod` release here means a NEW project is about to take over a live frontend.
|
|
221
|
+
let frontend = null;
|
|
222
|
+
if (appProject) {
|
|
223
|
+
try {
|
|
224
|
+
const r = await call(MANAGE, `/_api/wix-code-app-releases/v1/app-projects/${appProject.id}/app-releases/query`, { ...opts, body: { query: { cursorPaging: { limit: 20 } } } });
|
|
225
|
+
const prod = (r.appReleases ?? []).find((x) => x.releaseSlug === "prod");
|
|
226
|
+
frontend = prod
|
|
227
|
+
? { serving: true, releasedAt: prod.updatedDate ?? prod.createdDate ?? null, deploymentId: prod.appDeploymentId ?? null }
|
|
228
|
+
: { serving: false };
|
|
229
|
+
} catch (e) {
|
|
230
|
+
emit("note", { step: "releases", detail: String(e.message).slice(0, 200) });
|
|
231
|
+
frontend = { serving: null };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const note =
|
|
235
|
+
hosting === "self" ? "no Wix hosting: the frontend is yours to host; its origins must be on the OAuth app's allow-list"
|
|
236
|
+
: frontend?.serving === true
|
|
237
|
+
? `a frontend is SERVING at ${baseUrl}, released ${frontend.releasedAt}. This is a new project: a \`wix release\` from here replaces it (the current deployment keeps its own address and prod can be pointed back). Tell the user before releasing; unless the brief asked for a new frontend, ask.`
|
|
238
|
+
: frontend?.serving === false
|
|
239
|
+
? `${hosting === "created" ? "hosting created" : "hosting exists"} at ${baseUrl}; nothing served yet — the first release from this project fills it`
|
|
240
|
+
: frontend
|
|
241
|
+
? `could not read whether a frontend is serving at ${baseUrl}; check the address before releasing`
|
|
242
|
+
: undefined;
|
|
243
|
+
emit("attached", { siteId, appId, baseUrl, hosting, frontend, origins: hosting0 === "self" ? origins : undefined, note });
|
|
154
244
|
|
|
155
|
-
// ---- 2 · scaffold
|
|
245
|
+
// ---- 2 · scaffold (only where there is no project) -------------------------------------------------
|
|
156
246
|
mkdirSync(projectDir, { recursive: true });
|
|
157
|
-
if (stack === "astro") {
|
|
158
|
-
// The
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const sparse = spawnSync("git", ["-C", tmp, "sparse-checkout", "set", TEMPLATE_PATH], { encoding: "utf8", timeout: 60_000 });
|
|
164
|
-
if (sparse.status !== 0 || !existsSync(join(tmp, TEMPLATE_PATH, "package.json"))) fail("scaffold", sparse.stderr || `template ${TEMPLATE_PATH} not found in ${TEMPLATES_REPO}`);
|
|
165
|
-
cpSync(join(tmp, TEMPLATE_PATH), projectDir, { recursive: true, force: false, errorOnExist: false });
|
|
166
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
247
|
+
if (stack === "astro" && mode === "scaffold") {
|
|
248
|
+
// The first vertical's composed template: the CLI's blank scaffold with the vertical deployed
|
|
249
|
+
// and its lockfile, the same folder `wix create --template-path` copies for a new site. Copied
|
|
250
|
+
// here because the CLI's create makes a new site and this folder gets an existing one. Further
|
|
251
|
+
// verticals are deployed below.
|
|
252
|
+
cpSync(join(templatesDir({ need: `${verticals[0]}/project` }), verticals[0], "project"), projectDir, { recursive: true, force: false, errorOnExist: false });
|
|
167
253
|
const pkgPath = join(projectDir, "package.json");
|
|
168
254
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
169
255
|
pkg.name = folderName;
|
|
170
|
-
pkg.scripts = { astro: "astro", dev: "wix dev", build: "wix build", wix: "wix", preview: "wix preview", release: "wix release", generate: "wix generate", env: "wix env", skills: "wix skills" };
|
|
171
|
-
pkg.devDependencies = {
|
|
172
|
-
...(pkg.devDependencies ?? {}),
|
|
173
|
-
"@astrojs/react": "^4.3.0",
|
|
174
|
-
"@types/react": "^18.3.1",
|
|
175
|
-
"@types/react-dom": "^18.3.1",
|
|
176
|
-
"@wix/cli": "^1.1.92",
|
|
177
|
-
"@wix/astro-wix-hosting-adapter": "^2.0.0",
|
|
178
|
-
react: "18.3.1",
|
|
179
|
-
"react-dom": "18.3.1",
|
|
180
|
-
};
|
|
181
256
|
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
182
|
-
writeFileSync(join(projectDir, "astro.config.mjs"), `// @ts-check
|
|
183
|
-
import { defineConfig } from "astro/config";
|
|
184
|
-
import wix from "@wix/astro";
|
|
185
|
-
import wixPages from "@wix/astro-pages";
|
|
186
|
-
import react from "@astrojs/react";
|
|
187
|
-
import wixHostingAdapter from "@wix/astro-wix-hosting-adapter";
|
|
188
|
-
|
|
189
|
-
// https://astro.build/config
|
|
190
|
-
export default defineConfig({
|
|
191
|
-
integrations: [wix(), wixPages(), react()],
|
|
192
|
-
security: { checkOrigin: false },
|
|
193
|
-
adapter: wixHostingAdapter(),
|
|
194
|
-
image: { domains: ["static.wixstatic.com"] },
|
|
195
|
-
output: "server",
|
|
196
|
-
});
|
|
197
|
-
`);
|
|
198
257
|
const gi = join(projectDir, ".gitignore");
|
|
199
258
|
const cur = existsSync(gi) ? readFileSync(gi, "utf8") : "";
|
|
200
259
|
if (!/\.env/.test(cur)) writeFileSync(gi, cur + "\n# local env (pulled from Wix)\n.env.local\n.env\n");
|
|
@@ -211,15 +270,18 @@ writeFileSync(join(projectDir, ".env.local"), [
|
|
|
211
270
|
`WIX_CLIENT_SECRET=${quote(secrets.appSecret)}`,
|
|
212
271
|
"",
|
|
213
272
|
].join("\n"));
|
|
214
|
-
emit("scaffolded", { folder: folderName, stack, template: stack === "astro" ?
|
|
273
|
+
emit(mode === "link" ? "linked" : mode === "config-only" ? "configured" : "scaffolded", { folder: folderName, stack, template: mode === "scaffold" && stack === "astro" ? join(TEMPLATES, verticals[0], "project") : null });
|
|
274
|
+
// the agent config files `wix create` writes (attach never runs the CLI's scaffold at all); fill-only
|
|
275
|
+
emit("agent_configs", writeAgentsMd(projectDir, { skill: basename(SKILL_ROOT), stack }));
|
|
215
276
|
|
|
216
|
-
if (stack !== "astro") {
|
|
217
|
-
emit("ready", { projectDir, siteId, appId, baseUrl, hosting, stack, dashboardUrl: `https://manage.wix.com/dashboard/${siteId}`,
|
|
218
|
-
next: `scaffold the ${stack} project in this folder per SKILL.md, then deploy.mjs <vertical…> --stack ${stack} (the client id is read from wix.config.json); no seed — the site owns its content`
|
|
277
|
+
if (mode !== "link" && (stack !== "astro" || mode === "config-only")) {
|
|
278
|
+
emit("ready", { projectDir, siteId, appId, baseUrl, hosting, frontend, stack, dashboardUrl: `https://manage.wix.com/dashboard/${siteId}`,
|
|
279
|
+
next: `scaffold the ${stack} project in this folder per SKILL.md, then deploy.mjs <vertical…> --stack ${stack} (the client id is read from wix.config.json); no seed — the site owns its content` +
|
|
280
|
+
(hosting === "self" ? `; you host it: origins on the OAuth app allow-list now: ${origins.join(", ") || "none — add them before the first checkout test"}` : "") });
|
|
219
281
|
process.exit(0);
|
|
220
282
|
}
|
|
221
283
|
|
|
222
|
-
// ---- 3 · deploy shipped code + deps
|
|
284
|
+
// ---- 3 · deploy shipped code + deps (adds nothing to a scaffold from the template) --------------
|
|
223
285
|
let deployResult = {};
|
|
224
286
|
{
|
|
225
287
|
const deploy = spawnSync("node", [join(SKILL_ROOT, "install", "deploy.mjs"), ...verticals, "--stack", stack], { cwd: projectDir, encoding: "utf8", timeout: 60_000 });
|
|
@@ -229,12 +291,16 @@ let deployResult = {};
|
|
|
229
291
|
emit("deployed", deployResult);
|
|
230
292
|
}
|
|
231
293
|
|
|
232
|
-
// ---- 4 · dependency install, detached
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
294
|
+
// ---- 4 · dependency install, detached (any project with a package.json) --------------------------
|
|
295
|
+
let install = null;
|
|
296
|
+
if (existsSync(join(projectDir, "package.json"))) {
|
|
297
|
+
const installLog = join(projectDir, "npm-install.log");
|
|
298
|
+
const logFd = openSync(installLog, "a");
|
|
299
|
+
const child = spawn("sh", ["-c", existsSync(join(projectDir, "package-lock.json")) ? "npm ci --ignore-scripts || npm install --ignore-scripts" : "npm install --ignore-scripts"], { cwd: projectDir, detached: true, stdio: ["ignore", logFd, logFd] });
|
|
300
|
+
child.unref();
|
|
301
|
+
install = { log: installLog, doneMarker: "node_modules/.package-lock.json" };
|
|
302
|
+
emit("install_started", install);
|
|
303
|
+
}
|
|
238
304
|
|
|
239
305
|
// ---- done ----------------------------------------------------------------------------------------
|
|
240
306
|
emit("ready_for_brand_layer", {
|
|
@@ -243,11 +309,20 @@ emit("ready_for_brand_layer", {
|
|
|
243
309
|
appId,
|
|
244
310
|
baseUrl,
|
|
245
311
|
hosting,
|
|
312
|
+
frontend,
|
|
246
313
|
verticals,
|
|
247
314
|
dashboardUrl: `https://manage.wix.com/dashboard/${siteId}`,
|
|
248
315
|
productsUrl: deployResult.productsUrl,
|
|
249
316
|
categoriesUrl: deployResult.categoriesUrl,
|
|
250
|
-
|
|
317
|
+
mode,
|
|
318
|
+
stack,
|
|
319
|
+
install,
|
|
251
320
|
seed: null,
|
|
252
|
-
next:
|
|
321
|
+
next:
|
|
322
|
+
"the site's content is live already — nothing to seed; get the measure of the site (SKILL.md step 3), theme + write the pages" +
|
|
323
|
+
(mode === "link" && hosting !== "self" ? "; make the project what its stack needs on Wix hosting (SKILL.md step 1)" : "") +
|
|
324
|
+
(install ? "; wait for the install marker" : "") +
|
|
325
|
+
(hosting === "self"
|
|
326
|
+
? `; you host it — no wix release; origins on the OAuth app allow-list now: ${origins.join(", ") || "none — add them before the first checkout test"}; add the public one when it goes live`
|
|
327
|
+
: "; then release as step 5 says for the stack"),
|
|
253
328
|
});
|
|
@@ -43,21 +43,25 @@ import {
|
|
|
43
43
|
} from "node:fs";
|
|
44
44
|
import { dirname, join, resolve } from "node:path";
|
|
45
45
|
import { fileURLToPath } from "node:url";
|
|
46
|
+
import { templatesDir } from "./templates.mjs";
|
|
47
|
+
import { syncLockRoot } from "./lock.mjs";
|
|
46
48
|
|
|
47
49
|
const SKILL_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
48
|
-
|
|
50
|
+
// The shipped code: the repository's templates/ (a checkout, the cache, or fetched now).
|
|
51
|
+
const REF = templatesDir();
|
|
49
52
|
const PROJECT = process.cwd();
|
|
50
53
|
const SRC = join(PROJECT, "src");
|
|
51
54
|
const CONFIG_TS = join(SRC, "wix", "config.ts");
|
|
52
55
|
const PKG_JSON = join(PROJECT, "package.json");
|
|
53
56
|
|
|
54
|
-
// The vertical registry: every directory under
|
|
57
|
+
// The vertical registry: every directory under templates/ that ships an app/ is a vertical.
|
|
55
58
|
const VERTICALS = readdirSync(REF, { withFileTypes: true })
|
|
56
59
|
.filter(
|
|
57
60
|
(d) =>
|
|
58
61
|
d.isDirectory() &&
|
|
59
62
|
existsSync(join(REF, d.name, "app")) &&
|
|
60
|
-
d.name !== "shared"
|
|
63
|
+
d.name !== "shared" &&
|
|
64
|
+
d.name !== "blank",
|
|
61
65
|
)
|
|
62
66
|
.map((d) => d.name);
|
|
63
67
|
|
|
@@ -73,8 +77,6 @@ const SHARED_DEPS = {
|
|
|
73
77
|
};
|
|
74
78
|
const CAPABILITY_DEPS = {
|
|
75
79
|
"media-upload": {
|
|
76
|
-
// All shipped Astro locks already carry @wix/media >= 1.0.271 transitively. Keep this
|
|
77
|
-
// range compatible with them, then promote it to a root lock dependency below.
|
|
78
80
|
"@wix/media": "^1.0.271",
|
|
79
81
|
"@wix/essentials": "^1.0.10",
|
|
80
82
|
},
|
|
@@ -179,7 +181,7 @@ const flagArgs = new Set(
|
|
|
179
181
|
);
|
|
180
182
|
const requested = [...new Set(argv.filter((a) => !flagArgs.has(a)))];
|
|
181
183
|
|
|
182
|
-
const result = { stack, verticals: [], skillRoot: SKILL_ROOT };
|
|
184
|
+
const result = { stack, verticals: [], skillRoot: SKILL_ROOT, templates: REF };
|
|
183
185
|
|
|
184
186
|
if (!["astro", "react", "lib", "static"].includes(stack)) {
|
|
185
187
|
console.log(
|
|
@@ -362,13 +364,6 @@ if (result.verticals.length && existsSync(PKG_JSON)) {
|
|
|
362
364
|
if (added.length)
|
|
363
365
|
writeFileSync(PKG_JSON, JSON.stringify(pkg, null, 2) + "\n");
|
|
364
366
|
result.depsAdded = added.map(([name]) => name);
|
|
365
|
-
if (added.length)
|
|
366
|
-
result.note = [
|
|
367
|
-
result.note,
|
|
368
|
-
"run `npm install --ignore-scripts` to pick up depsAdded",
|
|
369
|
-
]
|
|
370
|
-
.filter(Boolean)
|
|
371
|
-
.join("; ");
|
|
372
367
|
} else if (result.verticals.length) {
|
|
373
368
|
result.depsAdded = [];
|
|
374
369
|
result.note = [
|
|
@@ -379,54 +374,20 @@ if (result.verticals.length && existsSync(PKG_JSON)) {
|
|
|
379
374
|
.join("; ");
|
|
380
375
|
}
|
|
381
376
|
|
|
382
|
-
// ----
|
|
383
|
-
// A
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
//
|
|
387
|
-
//
|
|
388
|
-
// and the `|| npm install` fallback self-heals.
|
|
377
|
+
// ---- the project's lockfile ---------------------------------------------------------------------
|
|
378
|
+
// A project created from a composed template (templates/<vertical>/project) carries that
|
|
379
|
+
// template's package-lock.json, so `npm ci` installs it without resolving. When this run added
|
|
380
|
+
// dependencies to package.json, the lock's root entry is brought in line where the tree already
|
|
381
|
+
// holds the package (install/lock.mjs); anything the tree lacks makes `npm ci` fail fast and the
|
|
382
|
+
// `|| npm install` fallback resolve it. A project without a lock installs with `npm install`.
|
|
389
383
|
const PROJECT_LOCK = join(PROJECT, "package-lock.json");
|
|
390
|
-
if (
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
)
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
result.verticals[0],
|
|
398
|
-
"lock",
|
|
399
|
-
stack,
|
|
400
|
-
"package-lock.json",
|
|
401
|
-
);
|
|
402
|
-
if (existsSync(shippedLock)) {
|
|
403
|
-
cpSync(shippedLock, PROJECT_LOCK);
|
|
404
|
-
if (uploadPolicies.length) {
|
|
405
|
-
// The supplied per-vertical lock already resolves Media + Essentials transitively. Add
|
|
406
|
-
// them to its root package entry too, so npm ci accepts package.json's new direct
|
|
407
|
-
// dependency without falling back to a slow dependency-resolution install.
|
|
408
|
-
const lock = JSON.parse(readFileSync(PROJECT_LOCK, "utf8"));
|
|
409
|
-
lock.packages ??= {};
|
|
410
|
-
lock.packages[""] ??= {};
|
|
411
|
-
lock.packages[""].dependencies ??= {};
|
|
412
|
-
const rootDeps = lock.packages[""].dependencies;
|
|
413
|
-
for (const [name, range] of Object.entries(CAPABILITY_DEPS["media-upload"])) {
|
|
414
|
-
if (!lock.packages?.[`node_modules/${name}`]) {
|
|
415
|
-
result.lockCapability = `UNPATCHED — supplied lock lacks ${name}; npm install will resolve it`;
|
|
416
|
-
break;
|
|
417
|
-
}
|
|
418
|
-
rootDeps[name] = range;
|
|
419
|
-
}
|
|
420
|
-
writeFileSync(PROJECT_LOCK, JSON.stringify(lock, null, 2) + "\n");
|
|
421
|
-
if (!result.lockCapability) result.lockCapability = "media_upload_promoted";
|
|
422
|
-
}
|
|
423
|
-
result.lockDeployed = true;
|
|
424
|
-
result.note = [
|
|
425
|
-
result.note,
|
|
426
|
-
"install with `npm ci --ignore-scripts || npm install --ignore-scripts`",
|
|
427
|
-
]
|
|
428
|
-
.filter(Boolean)
|
|
429
|
-
.join("; ");
|
|
384
|
+
if (result.verticals.length && existsSync(PKG_JSON)) {
|
|
385
|
+
if (existsSync(PROJECT_LOCK)) {
|
|
386
|
+
const sync = syncLockRoot(PROJECT);
|
|
387
|
+
if (sync && (sync.promoted.length || sync.missing.length)) result.lock = sync;
|
|
388
|
+
result.note = [result.note, "install with `npm ci --ignore-scripts || npm install --ignore-scripts`"].filter(Boolean).join("; ");
|
|
389
|
+
} else if (result.depsAdded?.length) {
|
|
390
|
+
result.note = [result.note, "run `npm install --ignore-scripts` to pick up depsAdded"].filter(Boolean).join("; ");
|
|
430
391
|
}
|
|
431
392
|
}
|
|
432
393
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Keep a project's package-lock.json valid for `npm ci` after package.json gained dependencies.
|
|
2
|
+
// `npm ci` refuses a lock whose root entry disagrees with package.json. When the dependency deploy
|
|
3
|
+
// added is already in the lock's tree (pulled in by something else), declaring it in the root entry
|
|
4
|
+
// too is all `npm ci` needs; a dependency the tree lacks is left for `npm install` to resolve.
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
|
|
8
|
+
const parse = (v) => {
|
|
9
|
+
const m = String(v).match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
10
|
+
return m ? m.slice(1).map(Number) : null;
|
|
11
|
+
};
|
|
12
|
+
const cmp = (a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
|
|
13
|
+
|
|
14
|
+
// The ranges deploy writes: exact, ^x.y.z, ~x.y.z, >=x.y.z. Anything else is "not known to fit".
|
|
15
|
+
export function satisfies(version, range) {
|
|
16
|
+
const v = parse(version);
|
|
17
|
+
const m = String(range).trim().match(/^(\^|~|>=)?\s*v?(\d+\.\d+\.\d+)/);
|
|
18
|
+
if (!v || !m) return false;
|
|
19
|
+
const r = parse(m[2]);
|
|
20
|
+
const op = m[1] ?? "";
|
|
21
|
+
if (op === "") return cmp(v, r) === 0;
|
|
22
|
+
if (cmp(v, r) < 0) return false;
|
|
23
|
+
if (op === ">=") return true;
|
|
24
|
+
if (op === "~") return v[0] === r[0] && v[1] === r[1];
|
|
25
|
+
// caret: same major; for 0.x, same minor
|
|
26
|
+
return r[0] > 0 ? v[0] === r[0] : v[0] === 0 && v[1] === r[1];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Returns null when there is no lock; else {promoted, missing}. Writes the lock only when it changed.
|
|
30
|
+
export function syncLockRoot(projectDir) {
|
|
31
|
+
const lockPath = join(projectDir, "package-lock.json");
|
|
32
|
+
const pkgPath = join(projectDir, "package.json");
|
|
33
|
+
if (!existsSync(lockPath) || !existsSync(pkgPath)) return null;
|
|
34
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
35
|
+
const lock = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
36
|
+
lock.packages ??= {};
|
|
37
|
+
const root = (lock.packages[""] ??= {});
|
|
38
|
+
const promoted = [], missing = [];
|
|
39
|
+
let changed = false;
|
|
40
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
41
|
+
for (const [name, range] of Object.entries(pkg[field] ?? {})) {
|
|
42
|
+
if (root[field]?.[name] === range) continue;
|
|
43
|
+
const inTree = lock.packages[`node_modules/${name}`];
|
|
44
|
+
if (inTree && satisfies(inTree.version, range)) {
|
|
45
|
+
(root[field] ??= {})[name] = range;
|
|
46
|
+
promoted.push(name);
|
|
47
|
+
changed = true;
|
|
48
|
+
} else {
|
|
49
|
+
missing.push(name);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (changed) writeFileSync(lockPath, JSON.stringify(lock, null, 2) + "\n");
|
|
54
|
+
return { promoted, missing };
|
|
55
|
+
}
|