@wix/agent-skills 1.17.0 → 1.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +115 -12
- package/skills/wix-app/references/APP_MARKET_REVIEW.md +1 -1
- package/skills/wix-app/references/BACKEND_API.md +18 -0
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +6 -0
- package/skills/wix-app/references/DASHBOARD_MODAL.md +10 -2
- package/skills/wix-app/references/DASHBOARD_PAGE.md +32 -70
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +74 -83
- package/skills/wix-app/references/SITE_PLUGIN.md +12 -0
- package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
- package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
- package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
- package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +12 -11
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +1 -0
- package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +16 -8
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +47 -14
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +3 -0
- package/skills/wix-base44-connector/SKILL.md +133 -44
- package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
- package/skills/wix-base44-connector/scripts/utils.js +216 -30
- package/skills/wix-headless/entry/skill.md +1 -1
- package/skills/wix-headless/references/CAPABILITIES.md +9 -1
- package/skills/wix-headless/references/DESIGN.md +1 -0
- package/skills/wix-headless/references/DISCOVERY.md +2 -1
- package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
- package/skills/wix-headless/references/SDK_HANDOFF.md +4 -1
- package/skills/wix-headless/references/SEED.md +2 -1
- package/skills/wix-headless/references/SETUP.md +1 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +26 -8
- package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
- package/skills/wix-headless/references/inline-recipes/setup-forms.md +57 -10
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
- package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
- package/skills/wix-headless/references/non-astro.md +1 -1
- package/skills/wix-headless-fast/SKILL.md +166 -0
- package/skills/wix-headless-fast/entry/skill.md +99 -0
- package/skills/wix-headless-fast/install/deploy.mjs +433 -0
- package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
- package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
- package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
- package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
- package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
- package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
- package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
- package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
- package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
- package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
- package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
- package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
- package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
- package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
- package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
- package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
- package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
- package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
- package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
- package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
- package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
- package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
- package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
- package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
- package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
- package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
- package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
- package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
- package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
- package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
- package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
- package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
- package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
- package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
- package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
- package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
- package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
- package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
- package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
- package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
- package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
- package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
- package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
- package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
- package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
- package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
- package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
- package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
- package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
- package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
- package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
- package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
- package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
- package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
- package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
- package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
- package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
- package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
- package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
- package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
- package/skills/wix-manage/SKILL.md +113 -89
- package/skills/wix-manage/references/dashboard-navigation/routes.json +12 -52
- package/skills/wix-manage/references/ecommerce/shipping/ecom-shipping-api.md +0 -2
- package/skills/wix-manage/references/forms/create-form.md +272 -184
- package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +13 -10
- package/skills/wix-manage/references/forms/update-form.md +122 -0
- package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
- package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
- package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
- package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
- package/skills/wix-manage/references/media/generate-image-with-ai.md +86 -0
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +37 -7
- package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
- package/skills/wix-vibe-headless/SKILL.md +18 -4
- package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
- package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +3 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +3 -1
- package/skills/wix-vibe-headless/platforms/base44.md +27 -61
- package/skills/wix-vibe-headless/platforms/generic.md +6 -3
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +43 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
- package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
- package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
- package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +486 -0
- package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
- package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
- package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
- package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
- package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1836 -0
- package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +137 -84
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
- package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
- package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
- package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
// Deploy the shipped code into the project. Run from the PROJECT ROOT:
|
|
2
|
+
//
|
|
3
|
+
// node <SKILL_ROOT>/install/deploy.mjs <vertical> [<vertical> …] --stack astro|react [--client-id <id>] [--plan plan.json]
|
|
4
|
+
//
|
|
5
|
+
// --stack astro (default) — copies each vertical's framework-agnostic core (app/) AND its
|
|
6
|
+
// Astro overlay (app-astro/: pages, layouts) into src/. Ambient auth: no
|
|
7
|
+
// client id is needed or written.
|
|
8
|
+
// --stack react — copies only the core (app/) into src/, and writes the public OAuth
|
|
9
|
+
// client id into src/wix/config.ts (pass --client-id, or it's read from
|
|
10
|
+
// wix.config.json's appId when present).
|
|
11
|
+
//
|
|
12
|
+
// TWO mechanisms, driven by the same vertical arguments:
|
|
13
|
+
// 1. Recursive file copy with force:false — only files that AREN'T there yet are written, so
|
|
14
|
+
// a re-run restores missing files without clobbering edits, and a later call can add a
|
|
15
|
+
// vertical safely. Verticals ship at disjoint paths (src/wix/<vertical>/,
|
|
16
|
+
// src/components/<vertical>/, …), so they never collide with each other.
|
|
17
|
+
// 2. package.json dependency patch — after the copy, any dependency the copied code imports
|
|
18
|
+
// that is absent from BOTH dependencies and devDependencies is added to dependencies
|
|
19
|
+
// (fill-only: an existing version range always wins). The script never runs npm install —
|
|
20
|
+
// it only makes package.json truthful about what src/ imports; installing is the caller's
|
|
21
|
+
// one command afterwards.
|
|
22
|
+
import {
|
|
23
|
+
cpSync,
|
|
24
|
+
existsSync,
|
|
25
|
+
readFileSync,
|
|
26
|
+
writeFileSync,
|
|
27
|
+
readdirSync,
|
|
28
|
+
} from "node:fs";
|
|
29
|
+
import { dirname, join, resolve } from "node:path";
|
|
30
|
+
import { fileURLToPath } from "node:url";
|
|
31
|
+
|
|
32
|
+
const SKILL_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
33
|
+
const REF = join(SKILL_ROOT, "references");
|
|
34
|
+
const PROJECT = process.cwd();
|
|
35
|
+
const SRC = join(PROJECT, "src");
|
|
36
|
+
const CONFIG_TS = join(SRC, "wix", "config.ts");
|
|
37
|
+
const PKG_JSON = join(PROJECT, "package.json");
|
|
38
|
+
|
|
39
|
+
// The vertical registry: every directory under references/ that ships an app/ is a vertical.
|
|
40
|
+
const VERTICALS = readdirSync(REF, { withFileTypes: true })
|
|
41
|
+
.filter(
|
|
42
|
+
(d) =>
|
|
43
|
+
d.isDirectory() &&
|
|
44
|
+
existsSync(join(REF, d.name, "app")) &&
|
|
45
|
+
d.name !== "shared",
|
|
46
|
+
)
|
|
47
|
+
.map((d) => d.name);
|
|
48
|
+
|
|
49
|
+
// What the shipped code imports, declared per layer (version ranges are the ones the shipped
|
|
50
|
+
// code was verified against). react/astro/typescript/@wix/astro* are scaffold-owned — never
|
|
51
|
+
// listed here. A new vertical adds its own entry; the patch logic below never changes.
|
|
52
|
+
const SHARED_DEPS = {
|
|
53
|
+
"@wix/sdk": "^1.21.5",
|
|
54
|
+
// The shipped components style themselves with Tailwind v4 utilities reading the @theme
|
|
55
|
+
// tokens in styles/global.css (the same system the official Wix headless templates use).
|
|
56
|
+
tailwindcss: "^4.1.7",
|
|
57
|
+
"@tailwindcss/vite": "^4.1.7",
|
|
58
|
+
};
|
|
59
|
+
const CAPABILITY_DEPS = {
|
|
60
|
+
"media-upload": {
|
|
61
|
+
// All shipped Astro locks already carry @wix/media >= 1.0.271 transitively. Keep this
|
|
62
|
+
// range compatible with them, then promote it to a root lock dependency below.
|
|
63
|
+
"@wix/media": "^1.0.271",
|
|
64
|
+
"@wix/essentials": "^1.0.10",
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
const VERTICAL_DEPS = {
|
|
68
|
+
storefront: {
|
|
69
|
+
core: {
|
|
70
|
+
"@wix/stores": "^1.0.888",
|
|
71
|
+
"@wix/categories": "^1.0.220",
|
|
72
|
+
"@wix/ecom": "^1.0.2451",
|
|
73
|
+
"@wix/redirects": "^1.0.125",
|
|
74
|
+
},
|
|
75
|
+
astro: {
|
|
76
|
+
"@wix/seo": "^1.0.79",
|
|
77
|
+
"@wix/essentials": "^1.0.6",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
bookings: {
|
|
81
|
+
core: {
|
|
82
|
+
"@wix/bookings": "^1.0.1650",
|
|
83
|
+
"@wix/auto_sdk_ecom_cart-v-2": "^1.0.192",
|
|
84
|
+
"@wix/forms": "^1.0.500",
|
|
85
|
+
"@wix/redirects": "^1.0.125",
|
|
86
|
+
},
|
|
87
|
+
astro: {
|
|
88
|
+
"@wix/seo": "^1.0.79",
|
|
89
|
+
"@wix/essentials": "^1.0.6",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
blog: {
|
|
93
|
+
core: {
|
|
94
|
+
"@wix/blog": "^1.0.645",
|
|
95
|
+
"@wix/ricos": "^11.12.0",
|
|
96
|
+
},
|
|
97
|
+
astro: {
|
|
98
|
+
"@wix/seo": "^1.0.79",
|
|
99
|
+
"@wix/essentials": "^1.0.10", // WIX_APPS.blogs needs ≥1.0.10
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
cms: {
|
|
103
|
+
core: {
|
|
104
|
+
"@wix/data": "^1.0.512",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
forms: {
|
|
108
|
+
core: {
|
|
109
|
+
"@wix/forms": "^1.0.501",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
events: {
|
|
113
|
+
core: {
|
|
114
|
+
"@wix/events": "^1.0.860",
|
|
115
|
+
"@wix/redirects": "^1.0.125",
|
|
116
|
+
},
|
|
117
|
+
astro: {
|
|
118
|
+
"@wix/seo": "^1.0.79",
|
|
119
|
+
"@wix/essentials": "^1.0.10",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
members: {
|
|
123
|
+
core: {
|
|
124
|
+
"@wix/members": "^1.0.511",
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
portfolio: {
|
|
128
|
+
core: {
|
|
129
|
+
"@wix/portfolio": "^1.0.229",
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
"pricing-plans": {
|
|
133
|
+
core: {
|
|
134
|
+
"@wix/pricing-plans": "^1.0.378",
|
|
135
|
+
"@wix/redirects": "^1.0.125",
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
restaurants: {
|
|
139
|
+
core: {
|
|
140
|
+
"@wix/restaurants": "^1.0.525",
|
|
141
|
+
"@wix/table-reservations": "^1.0.397",
|
|
142
|
+
"@wix/ecom": "^1.0.2454",
|
|
143
|
+
"@wix/redirects": "^1.0.125",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const COPY = { recursive: true, force: false, errorOnExist: false };
|
|
149
|
+
|
|
150
|
+
// ---- args ---------------------------------------------------------------------------------------
|
|
151
|
+
const argv = process.argv.slice(2);
|
|
152
|
+
const flag = (name) => {
|
|
153
|
+
const i = argv.indexOf(`--${name}`);
|
|
154
|
+
return i !== -1 && argv[i + 1] && !argv[i + 1].startsWith("--")
|
|
155
|
+
? argv[i + 1]
|
|
156
|
+
: null;
|
|
157
|
+
};
|
|
158
|
+
const stack = flag("stack") ?? "astro";
|
|
159
|
+
const clientIdFlag = flag("client-id");
|
|
160
|
+
const planPath = flag("plan");
|
|
161
|
+
const flagArgs = new Set(
|
|
162
|
+
["--stack", "--client-id", "--plan", stack, clientIdFlag, planPath].filter(Boolean),
|
|
163
|
+
);
|
|
164
|
+
const requested = [...new Set(argv.filter((a) => !flagArgs.has(a)))];
|
|
165
|
+
|
|
166
|
+
const result = { stack, verticals: [], skillRoot: SKILL_ROOT };
|
|
167
|
+
|
|
168
|
+
if (!["astro", "react"].includes(stack)) {
|
|
169
|
+
console.log(
|
|
170
|
+
JSON.stringify({
|
|
171
|
+
error: `unknown --stack "${stack}" — expected astro|react`,
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let plan = {};
|
|
178
|
+
if (planPath) {
|
|
179
|
+
if (!existsSync(planPath)) {
|
|
180
|
+
console.log(JSON.stringify({ error: `plan file not found: ${planPath}` }));
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
plan = JSON.parse(readFileSync(planPath, "utf8"));
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.log(JSON.stringify({ error: `invalid --plan JSON: ${error.message}` }));
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const uploadPolicies = plan.capabilities?.mediaUpload?.policies ?? [];
|
|
192
|
+
if (!Array.isArray(uploadPolicies)) {
|
|
193
|
+
console.log(JSON.stringify({ error: "plan.capabilities.mediaUpload.policies must be an array" }));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
if (uploadPolicies.length && stack !== "astro") {
|
|
197
|
+
console.log(JSON.stringify({ error: "mediaUpload currently requires --stack astro because it ships a validated server endpoint" }));
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
for (const policy of uploadPolicies) {
|
|
201
|
+
if (
|
|
202
|
+
!policy ||
|
|
203
|
+
typeof policy.id !== "string" ||
|
|
204
|
+
!Array.isArray(policy.accept) ||
|
|
205
|
+
!policy.accept.every((mime) => typeof mime === "string") ||
|
|
206
|
+
!Number.isSafeInteger(policy.maxBytes) ||
|
|
207
|
+
policy.maxBytes < 1
|
|
208
|
+
) {
|
|
209
|
+
console.log(JSON.stringify({ error: "each mediaUpload policy needs id, accept: string[], and positive integer maxBytes" }));
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ---- copy ---------------------------------------------------------------------------------------
|
|
215
|
+
// Shared core — always.
|
|
216
|
+
cpSync(join(REF, "shared", "app"), SRC, COPY);
|
|
217
|
+
|
|
218
|
+
if (uploadPolicies.length) {
|
|
219
|
+
cpSync(join(REF, "shared", "capabilities", "media-upload", "app"), SRC, COPY);
|
|
220
|
+
cpSync(join(REF, "shared", "capabilities", "media-upload", "app-astro"), SRC, COPY);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const unknown = requested.filter((v) => !VERTICALS.includes(v));
|
|
224
|
+
const wantedDeps = { ...SHARED_DEPS };
|
|
225
|
+
if (uploadPolicies.length) Object.assign(wantedDeps, CAPABILITY_DEPS["media-upload"]);
|
|
226
|
+
for (const vertical of requested.filter((v) => VERTICALS.includes(v))) {
|
|
227
|
+
cpSync(join(REF, vertical, "app"), SRC, COPY);
|
|
228
|
+
if (stack === "astro" && existsSync(join(REF, vertical, "app-astro"))) {
|
|
229
|
+
cpSync(join(REF, vertical, "app-astro"), SRC, COPY);
|
|
230
|
+
}
|
|
231
|
+
const deps = VERTICAL_DEPS[vertical] ?? {};
|
|
232
|
+
Object.assign(
|
|
233
|
+
wantedDeps,
|
|
234
|
+
deps.core,
|
|
235
|
+
stack === "astro" ? deps.astro : undefined,
|
|
236
|
+
);
|
|
237
|
+
result.verticals.push(vertical);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (uploadPolicies.length) {
|
|
241
|
+
const configDir = join(SRC, "wix", "media-upload");
|
|
242
|
+
const configFile = join(configDir, "policies.generated.ts");
|
|
243
|
+
// The generated file is data only. The shipped endpoint owns validation and elevation.
|
|
244
|
+
writeFileSync(
|
|
245
|
+
configFile,
|
|
246
|
+
`// Generated by wix-headless-fast install/deploy.mjs from plan.capabilities.mediaUpload.\n` +
|
|
247
|
+
`// Edit the plan and redeploy; do not add browser-controlled policy selection here.\n` +
|
|
248
|
+
`export const mediaUploadPolicies = ${JSON.stringify(uploadPolicies, null, 2)} as const;\n`,
|
|
249
|
+
);
|
|
250
|
+
result.capabilities = { mediaUpload: uploadPolicies.map((policy) => policy.id) };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ---- dependency patch (fill-only) ----------------------------------------------------------------
|
|
254
|
+
if (result.verticals.length && existsSync(PKG_JSON)) {
|
|
255
|
+
const pkg = JSON.parse(readFileSync(PKG_JSON, "utf8"));
|
|
256
|
+
pkg.dependencies ??= {};
|
|
257
|
+
const present = { ...pkg.devDependencies, ...pkg.dependencies };
|
|
258
|
+
const added = Object.entries(wantedDeps).filter(
|
|
259
|
+
([name]) => !(name in present),
|
|
260
|
+
);
|
|
261
|
+
for (const [name, range] of added) pkg.dependencies[name] = range;
|
|
262
|
+
if (added.length)
|
|
263
|
+
writeFileSync(PKG_JSON, JSON.stringify(pkg, null, 2) + "\n");
|
|
264
|
+
result.depsAdded = added.map(([name]) => name);
|
|
265
|
+
if (added.length)
|
|
266
|
+
result.note = [
|
|
267
|
+
result.note,
|
|
268
|
+
"run `npm install --ignore-scripts` to pick up depsAdded",
|
|
269
|
+
]
|
|
270
|
+
.filter(Boolean)
|
|
271
|
+
.join("; ");
|
|
272
|
+
} else if (result.verticals.length) {
|
|
273
|
+
result.depsAdded = [];
|
|
274
|
+
result.note = [
|
|
275
|
+
result.note,
|
|
276
|
+
"no package.json here — run deploy from the project root",
|
|
277
|
+
]
|
|
278
|
+
.filter(Boolean)
|
|
279
|
+
.join("; ");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ---- shipped lockfile (single vertical only) ------------------------------------------------------
|
|
283
|
+
// A pre-resolved package-lock.json covering the scaffold + this vertical's deps ships at
|
|
284
|
+
// references/<vertical>/lock/<stack>/package-lock.json. Placing it lets `npm ci` skip the whole
|
|
285
|
+
// resolution phase (seconds instead of minutes). URLs are canonical registry.npmjs.org form —
|
|
286
|
+
// npm substitutes the locally configured registry (mirrors/proxies) at fetch time. Placed only
|
|
287
|
+
// when the project has no lock of its own; if it ever drifts out of sync, `npm ci` fails fast
|
|
288
|
+
// and the `|| npm install` fallback self-heals.
|
|
289
|
+
const PROJECT_LOCK = join(PROJECT, "package-lock.json");
|
|
290
|
+
if (
|
|
291
|
+
result.verticals.length === 1 &&
|
|
292
|
+
existsSync(PKG_JSON) &&
|
|
293
|
+
!existsSync(PROJECT_LOCK)
|
|
294
|
+
) {
|
|
295
|
+
const shippedLock = join(
|
|
296
|
+
REF,
|
|
297
|
+
result.verticals[0],
|
|
298
|
+
"lock",
|
|
299
|
+
stack,
|
|
300
|
+
"package-lock.json",
|
|
301
|
+
);
|
|
302
|
+
if (existsSync(shippedLock)) {
|
|
303
|
+
cpSync(shippedLock, PROJECT_LOCK);
|
|
304
|
+
if (uploadPolicies.length) {
|
|
305
|
+
// The supplied per-vertical lock already resolves Media + Essentials transitively. Add
|
|
306
|
+
// them to its root package entry too, so npm ci accepts package.json's new direct
|
|
307
|
+
// dependency without falling back to a slow dependency-resolution install.
|
|
308
|
+
const lock = JSON.parse(readFileSync(PROJECT_LOCK, "utf8"));
|
|
309
|
+
lock.packages ??= {};
|
|
310
|
+
lock.packages[""] ??= {};
|
|
311
|
+
lock.packages[""].dependencies ??= {};
|
|
312
|
+
const rootDeps = lock.packages[""].dependencies;
|
|
313
|
+
for (const [name, range] of Object.entries(CAPABILITY_DEPS["media-upload"])) {
|
|
314
|
+
if (!lock.packages?.[`node_modules/${name}`]) {
|
|
315
|
+
result.lockCapability = `UNPATCHED — supplied lock lacks ${name}; npm install will resolve it`;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
rootDeps[name] = range;
|
|
319
|
+
}
|
|
320
|
+
writeFileSync(PROJECT_LOCK, JSON.stringify(lock, null, 2) + "\n");
|
|
321
|
+
if (!result.lockCapability) result.lockCapability = "media_upload_promoted";
|
|
322
|
+
}
|
|
323
|
+
result.lockDeployed = true;
|
|
324
|
+
result.note = [
|
|
325
|
+
result.note,
|
|
326
|
+
"install with `npm ci --ignore-scripts || npm install --ignore-scripts`",
|
|
327
|
+
]
|
|
328
|
+
.filter(Boolean)
|
|
329
|
+
.join("; ");
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ---- astro config: wire the Tailwind vite plugin ---------------------------------------------------
|
|
334
|
+
// The blank scaffold's astro.config.mjs has no Tailwind wiring. Fill-only, like everything
|
|
335
|
+
// else: patch only when the plugin isn't referenced yet, and only when both anchors are found.
|
|
336
|
+
const ASTRO_CONFIG = join(PROJECT, "astro.config.mjs");
|
|
337
|
+
if (stack === "astro" && result.verticals.length && existsSync(ASTRO_CONFIG)) {
|
|
338
|
+
const config = readFileSync(ASTRO_CONFIG, "utf8");
|
|
339
|
+
if (config.includes("@tailwindcss/vite")) {
|
|
340
|
+
result.astroConfig = "tailwind_already_wired";
|
|
341
|
+
} else if (config.includes("export default defineConfig({")) {
|
|
342
|
+
const patched =
|
|
343
|
+
`import tailwindcss from "@tailwindcss/vite";\n` +
|
|
344
|
+
config.replace(
|
|
345
|
+
"export default defineConfig({",
|
|
346
|
+
"export default defineConfig({\n vite: { plugins: [tailwindcss()] },",
|
|
347
|
+
);
|
|
348
|
+
writeFileSync(ASTRO_CONFIG, patched);
|
|
349
|
+
result.astroConfig = "tailwind_wired";
|
|
350
|
+
} else {
|
|
351
|
+
result.astroConfig =
|
|
352
|
+
"UNPATCHED — add `vite: { plugins: [tailwindcss()] }` (import from @tailwindcss/vite) to astro.config.mjs by hand";
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// ---- ready-made links -----------------------------------------------------------------------------
|
|
357
|
+
// Emit the siteId and the dashboard deep links so nothing downstream re-derives or retypes them.
|
|
358
|
+
const WIX_CONFIG = join(PROJECT, "wix.config.json");
|
|
359
|
+
if (existsSync(WIX_CONFIG)) {
|
|
360
|
+
const config = JSON.parse(readFileSync(WIX_CONFIG, "utf8"));
|
|
361
|
+
const siteId = config.siteId ?? config.projectId;
|
|
362
|
+
if (siteId) {
|
|
363
|
+
result.siteId = siteId;
|
|
364
|
+
result.dashboardUrl = `https://manage.wix.com/dashboard/${siteId}`;
|
|
365
|
+
if (result.verticals.includes("storefront")) {
|
|
366
|
+
result.productsUrl = `https://manage.wix.com/dashboard/${siteId}/wix-stores/products`;
|
|
367
|
+
result.categoriesUrl = `https://manage.wix.com/dashboard/${siteId}/wix-stores/categories/list`;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (unknown.length) {
|
|
373
|
+
result.error = `unknown vertical(s) ${unknown.map((v) => `"${v}"`).join(", ")} — available: ${VERTICALS.join(", ")}`;
|
|
374
|
+
}
|
|
375
|
+
if (!requested.length) {
|
|
376
|
+
result.note = `no vertical given — deployed the shared core only. Available: ${VERTICALS.join(", ")}`;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// ---- client ids ---------------------------------------------------------------------------------
|
|
380
|
+
// The shared data client is ambient on managed Astro. Members are different: their shipped
|
|
381
|
+
// custom credential flow always needs an explicit public OAuth client, including on Astro.
|
|
382
|
+
let clientId = clientIdFlag;
|
|
383
|
+
if (!clientId && existsSync(join(PROJECT, "wix.config.json"))) {
|
|
384
|
+
// On a Wix-managed project the public OAuth client id IS the appId.
|
|
385
|
+
clientId =
|
|
386
|
+
JSON.parse(readFileSync(join(PROJECT, "wix.config.json"), "utf8")).appId ??
|
|
387
|
+
null;
|
|
388
|
+
}
|
|
389
|
+
if (stack === "react") {
|
|
390
|
+
if (clientId) {
|
|
391
|
+
const current = readFileSync(CONFIG_TS, "utf8");
|
|
392
|
+
// A non-null id already set wins; only fill the shipped null placeholder.
|
|
393
|
+
if (/WIX_CLIENT_ID:\s*string\s*\|\s*null\s*=\s*null/.test(current)) {
|
|
394
|
+
writeFileSync(
|
|
395
|
+
CONFIG_TS,
|
|
396
|
+
current.replace(
|
|
397
|
+
/WIX_CLIENT_ID:\s*string\s*\|\s*null\s*=\s*null/,
|
|
398
|
+
`WIX_CLIENT_ID: string | null = "${clientId}"`,
|
|
399
|
+
),
|
|
400
|
+
);
|
|
401
|
+
result.clientId = "written";
|
|
402
|
+
} else {
|
|
403
|
+
result.clientId = "already_set";
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
result.clientId =
|
|
407
|
+
"missing — pass --client-id (react stack needs the public OAuth client id)";
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (requested.includes("members")) {
|
|
411
|
+
if (!clientId) {
|
|
412
|
+
result.membersClientId =
|
|
413
|
+
"missing — pass --client-id (custom members login needs the public OAuth client id)";
|
|
414
|
+
} else {
|
|
415
|
+
const current = readFileSync(CONFIG_TS, "utf8");
|
|
416
|
+
if (
|
|
417
|
+
/WIX_MEMBERS_CLIENT_ID:\s*string\s*\|\s*null\s*=\s*null/.test(current)
|
|
418
|
+
) {
|
|
419
|
+
writeFileSync(
|
|
420
|
+
CONFIG_TS,
|
|
421
|
+
current.replace(
|
|
422
|
+
/WIX_MEMBERS_CLIENT_ID:\s*string\s*\|\s*null\s*=\s*null/,
|
|
423
|
+
`WIX_MEMBERS_CLIENT_ID: string | null = "${clientId}"`,
|
|
424
|
+
),
|
|
425
|
+
);
|
|
426
|
+
result.membersClientId = "written";
|
|
427
|
+
} else {
|
|
428
|
+
result.membersClientId = "already_set";
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
console.log(JSON.stringify(result, null, 2));
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Fast path for a managed CREATE run — one deterministic call from "plan exists" to
|
|
2
|
+
// "brand layer can start". Composes the pieces that also remain individually runnable
|
|
3
|
+
// (deploy.mjs, the vertical's seed module); use those directly to recover a failed step,
|
|
4
|
+
// or for connect/iterate runs (which must NOT scaffold and don't use this script).
|
|
5
|
+
//
|
|
6
|
+
// node <SKILL_ROOT>/install/fast-path.mjs --business-name "<Brand>" --plan plan.json \
|
|
7
|
+
// --vertical <storefront|bookings|…> [--stack astro] [--folder-name <npm-safe-name>]
|
|
8
|
+
//
|
|
9
|
+
// It emits ONE JSON event per line and exits in ~35s with BOTH long steps — the dependency
|
|
10
|
+
// install AND the seed — running detached in the background (logs + completion markers
|
|
11
|
+
// reported in the final event), so the caller can build the brand layer while they finish.
|
|
12
|
+
// Steps: scaffold (Wix CLI; requires a logged-in session) → deploy shipped code + deps +
|
|
13
|
+
// lockfile → start `npm ci || npm install` detached → start the seed detached.
|
|
14
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
15
|
+
import { existsSync, openSync, readFileSync, readdirSync } from "node:fs";
|
|
16
|
+
import { dirname, join, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
18
|
+
|
|
19
|
+
const SKILL_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
|
+
|
|
21
|
+
const emit = (event, extra = {}) => console.log(JSON.stringify({ event, ...extra }));
|
|
22
|
+
const fail = (step, detail) => {
|
|
23
|
+
emit("error", { step, detail: String(detail).slice(0, 600) });
|
|
24
|
+
process.exit(1);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// ---- args ---------------------------------------------------------------------------------------
|
|
28
|
+
const argv = process.argv.slice(2);
|
|
29
|
+
const flag = (name) => {
|
|
30
|
+
const i = argv.indexOf(`--${name}`);
|
|
31
|
+
return i !== -1 && argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : null;
|
|
32
|
+
};
|
|
33
|
+
const businessName = flag("business-name");
|
|
34
|
+
const planPath = flag("plan");
|
|
35
|
+
const vertical = flag("vertical");
|
|
36
|
+
const stack = flag("stack") ?? "astro";
|
|
37
|
+
// --vertical is REQUIRED: a defaulted vertical deploys the wrong code and runs the wrong
|
|
38
|
+
// seed against the plan — fail loudly with the discovered choices instead.
|
|
39
|
+
const knownVerticals = readdirSync(join(SKILL_ROOT, "references"), { withFileTypes: true })
|
|
40
|
+
.filter((d) => d.isDirectory() && d.name !== "shared" && existsSync(join(SKILL_ROOT, "references", d.name, "app")))
|
|
41
|
+
.map((d) => d.name);
|
|
42
|
+
if (!businessName || !planPath || !vertical) {
|
|
43
|
+
fail("args", `usage: fast-path.mjs --business-name "<Brand>" --plan plan.json --vertical <${knownVerticals.join("|")}> [--stack astro]`);
|
|
44
|
+
}
|
|
45
|
+
if (!knownVerticals.includes(vertical)) {
|
|
46
|
+
fail("args", `unknown vertical "${vertical}" — shipped verticals: ${knownVerticals.join(", ")}`);
|
|
47
|
+
}
|
|
48
|
+
if (!existsSync(planPath)) fail("args", `plan file not found: ${planPath}`);
|
|
49
|
+
const plan = JSON.parse(readFileSync(planPath, "utf8"));
|
|
50
|
+
|
|
51
|
+
const folderName =
|
|
52
|
+
flag("folder-name") ??
|
|
53
|
+
businessName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
54
|
+
const projectDir = resolve(process.cwd(), folderName);
|
|
55
|
+
|
|
56
|
+
// ---- 1 · scaffold -------------------------------------------------------------------------------
|
|
57
|
+
if (existsSync(join(process.cwd(), "wix.config.json"))) {
|
|
58
|
+
fail("scaffold", "the current directory is already a Wix project — this script is for CREATE runs only; use deploy.mjs + the seed module directly");
|
|
59
|
+
}
|
|
60
|
+
if (existsSync(join(projectDir, "wix.config.json"))) {
|
|
61
|
+
emit("scaffold_skipped", { reason: "project already exists", folder: folderName });
|
|
62
|
+
} else {
|
|
63
|
+
emit("scaffolding", { folder: folderName });
|
|
64
|
+
const scaffold = spawnSync(
|
|
65
|
+
"npm",
|
|
66
|
+
["create", "@wix/new@latest", "--", "headless",
|
|
67
|
+
"--folder-name", folderName, "--business-name", businessName,
|
|
68
|
+
"--site-template", "--skip-install", "--no-publish"],
|
|
69
|
+
{ env: { ...process.env, CI: "1" }, encoding: "utf8", timeout: 300_000 },
|
|
70
|
+
);
|
|
71
|
+
if (scaffold.status !== 0 || !existsSync(join(projectDir, "wix.config.json"))) {
|
|
72
|
+
fail("scaffold", (scaffold.stderr || scaffold.stdout || "scaffold produced no wix.config.json — is the Wix CLI logged in? (npx @wix/cli@latest whoami)").slice(-600));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const wixConfig = JSON.parse(readFileSync(join(projectDir, "wix.config.json"), "utf8"));
|
|
76
|
+
const siteId = wixConfig.siteId ?? wixConfig.projectId;
|
|
77
|
+
emit("scaffolded", { folder: folderName, siteId });
|
|
78
|
+
|
|
79
|
+
// ---- 2 · deploy shipped code + deps + lockfile ---------------------------------------------------
|
|
80
|
+
const deploy = spawnSync(
|
|
81
|
+
"node",
|
|
82
|
+
[
|
|
83
|
+
join(SKILL_ROOT, "install", "deploy.mjs"),
|
|
84
|
+
vertical,
|
|
85
|
+
"--stack",
|
|
86
|
+
stack,
|
|
87
|
+
"--plan",
|
|
88
|
+
resolve(planPath),
|
|
89
|
+
],
|
|
90
|
+
{ cwd: projectDir, encoding: "utf8", timeout: 60_000 },
|
|
91
|
+
);
|
|
92
|
+
if (deploy.status !== 0) fail("deploy", deploy.stderr || deploy.stdout);
|
|
93
|
+
let deployResult = {};
|
|
94
|
+
try { deployResult = JSON.parse(deploy.stdout); } catch { /* keep going with raw output below */ }
|
|
95
|
+
if (deployResult.error) fail("deploy", deployResult.error);
|
|
96
|
+
emit("deployed", deployResult);
|
|
97
|
+
|
|
98
|
+
// ---- 3 · start the dependency install, detached --------------------------------------------------
|
|
99
|
+
const installLog = join(projectDir, "npm-install.log");
|
|
100
|
+
const logFd = openSync(installLog, "a");
|
|
101
|
+
const install = spawn("sh", ["-c", "npm ci --ignore-scripts || npm install --ignore-scripts"], {
|
|
102
|
+
cwd: projectDir,
|
|
103
|
+
detached: true,
|
|
104
|
+
stdio: ["ignore", logFd, logFd],
|
|
105
|
+
});
|
|
106
|
+
install.unref();
|
|
107
|
+
emit("install_started", { log: installLog, doneMarker: "node_modules/.package-lock.json" });
|
|
108
|
+
|
|
109
|
+
// ---- 4 · start the seed, detached ----------------------------------------------------------------
|
|
110
|
+
// The seed includes a Wix-side provisioning wait of unpredictable length (10-80s); running it
|
|
111
|
+
// in the caller's foreground would idle the agent for exactly that long. Detach it like the
|
|
112
|
+
// install: result JSON + exit-code marker land as files the caller syncs on before release.
|
|
113
|
+
const seedDir = join(SKILL_ROOT, "references", vertical, "seed");
|
|
114
|
+
const seedName = existsSync(seedDir)
|
|
115
|
+
? readdirSync(seedDir).find((f) => f.startsWith("seed-") && f.endsWith(".mjs"))
|
|
116
|
+
: undefined;
|
|
117
|
+
const seedFile = seedName ? join(seedDir, seedName) : null;
|
|
118
|
+
if (!seedFile) fail("seed", `no seed module found under ${seedDir}`);
|
|
119
|
+
const seedResultFile = join(projectDir, "seed-result.json");
|
|
120
|
+
const seedLog = join(projectDir, "seed.log");
|
|
121
|
+
const seedDoneMarker = join(projectDir, ".seed-exit");
|
|
122
|
+
const planAbs = resolve(planPath);
|
|
123
|
+
const seedChild = spawn(
|
|
124
|
+
"sh",
|
|
125
|
+
["-c", `node "${seedFile}" "${planAbs}" > seed-result.json 2> seed.log; echo $? > .seed-exit`],
|
|
126
|
+
{ cwd: projectDir, detached: true, stdio: "ignore" },
|
|
127
|
+
);
|
|
128
|
+
seedChild.unref();
|
|
129
|
+
emit("seeding_started", { vertical, resultFile: seedResultFile, log: seedLog, doneMarker: seedDoneMarker });
|
|
130
|
+
|
|
131
|
+
// ---- done ----------------------------------------------------------------------------------------
|
|
132
|
+
emit("ready_for_brand_layer", {
|
|
133
|
+
projectDir,
|
|
134
|
+
siteId,
|
|
135
|
+
dashboardUrl: deployResult.dashboardUrl,
|
|
136
|
+
productsUrl: deployResult.productsUrl,
|
|
137
|
+
categoriesUrl: deployResult.categoriesUrl,
|
|
138
|
+
install: { log: installLog, doneMarker: "node_modules/.package-lock.json" },
|
|
139
|
+
seed: { resultFile: "seed-result.json", log: "seed.log", doneMarker: ".seed-exit", success: "file contains 0" },
|
|
140
|
+
next: "theme SiteLayout + write the home page; then wait for BOTH done markers, verify .seed-exit is 0 (else read seed.log and re-run the seed module), build, release",
|
|
141
|
+
});
|