@wix/agent-skills 1.26.0 → 1.27.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/README.md +1 -0
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +7 -5
- package/skills/wix-app/references/DASHBOARD_PAGE.md +1 -1
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +14 -2
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +4 -5
- package/skills/wix-headless-kit/SKILL.md +31 -14
- package/skills/wix-headless-kit/guides/existing-site.md +12 -5
- package/skills/wix-headless-kit/install/attach.mjs +55 -10
- package/skills/wix-headless-kit/install/check.mjs +5 -5
- package/skills/wix-headless-kit/install/deploy.mjs +7 -3
- package/skills/wix-headless-kit/install/templates.mjs +21 -17
- package/skills/wix-headless-templates/SKILL.md +43 -0
- package/skills/wix-headless-templates/blank/project/README.md +15 -0
- package/skills/wix-headless-templates/blank/project/astro.config.mjs +20 -0
- package/skills/wix-headless-templates/blank/project/package.json +34 -0
- package/skills/wix-headless-templates/blank/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/blank/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/blank/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/blank/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/blank/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/blank/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/blank/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/blank/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/blank/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/blog/INSTRUCTIONS.md +418 -0
- package/skills/wix-headless-templates/blog/app/components/blog/BlogFeedView.tsx +191 -0
- package/skills/wix-headless-templates/blog/app/components/blog/CommentsView.tsx +206 -0
- package/skills/wix-headless-templates/blog/app/components/blog/PostLikeButton.tsx +62 -0
- package/skills/wix-headless-templates/blog/app/components/blog/PostView.tsx +139 -0
- package/skills/wix-headless-templates/blog/app/components/blog/RichContent.tsx +42 -0
- package/skills/wix-headless-templates/blog/app/hooks/blog/useBlogFeed.ts +31 -0
- package/skills/wix-headless-templates/blog/app/hooks/blog/useComments.ts +26 -0
- package/skills/wix-headless-templates/blog/app/hooks/blog/usePost.ts +25 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/authors-core.ts +51 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/authors.ts +50 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/blog-feed-store.ts +156 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/comments-core.ts +189 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/comments-store.ts +214 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/comments.ts +84 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/post-likes.ts +42 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/post-store.ts +158 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/posts-core.ts +347 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/posts.ts +132 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/taxonomy-core.ts +80 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/taxonomy.ts +78 -0
- package/skills/wix-headless-templates/blog/app/wix/blog/types.ts +161 -0
- package/skills/wix-headless-templates/blog/app-astro/layouts/SiteLayout.astro +44 -0
- package/skills/wix-headless-templates/blog/app-astro/pages/blog/[...slug].astro +148 -0
- package/skills/wix-headless-templates/blog/app-astro/pages/blog/category/[slug].astro +97 -0
- package/skills/wix-headless-templates/blog/app-astro/pages/blog/tag/[slug].astro +51 -0
- package/skills/wix-headless-templates/blog/app-astro/pages/blog.astro +34 -0
- package/skills/wix-headless-templates/blog/project/README.md +15 -0
- package/skills/wix-headless-templates/blog/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/blog/project/package-lock.json +14699 -0
- package/skills/wix-headless-templates/blog/project/package.json +39 -0
- package/skills/wix-headless-templates/blog/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/blog/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/blog/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/blog/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/blog/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/blog/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/blog/project/src/components/blog/BlogFeedView.tsx +191 -0
- package/skills/wix-headless-templates/blog/project/src/components/blog/CommentsView.tsx +206 -0
- package/skills/wix-headless-templates/blog/project/src/components/blog/PostLikeButton.tsx +62 -0
- package/skills/wix-headless-templates/blog/project/src/components/blog/PostView.tsx +139 -0
- package/skills/wix-headless-templates/blog/project/src/components/blog/RichContent.tsx +42 -0
- package/skills/wix-headless-templates/blog/project/src/hooks/blog/useBlogFeed.ts +31 -0
- package/skills/wix-headless-templates/blog/project/src/hooks/blog/useComments.ts +26 -0
- package/skills/wix-headless-templates/blog/project/src/hooks/blog/usePost.ts +25 -0
- package/skills/wix-headless-templates/blog/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/blog/project/src/layouts/SiteLayout.astro +44 -0
- package/skills/wix-headless-templates/blog/project/src/pages/blog/[...slug].astro +148 -0
- package/skills/wix-headless-templates/blog/project/src/pages/blog/category/[slug].astro +97 -0
- package/skills/wix-headless-templates/blog/project/src/pages/blog/tag/[slug].astro +51 -0
- package/skills/wix-headless-templates/blog/project/src/pages/blog.astro +34 -0
- package/skills/wix-headless-templates/blog/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/blog/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/authors-core.ts +51 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/authors.ts +50 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/blog-feed-store.ts +156 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/comments-core.ts +189 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/comments-store.ts +214 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/comments.ts +84 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/post-likes.ts +42 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/post-store.ts +158 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/posts-core.ts +347 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/posts.ts +132 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/taxonomy-core.ts +80 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/taxonomy.ts +78 -0
- package/skills/wix-headless-templates/blog/project/src/wix/blog/types.ts +161 -0
- package/skills/wix-headless-templates/blog/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/blog/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/blog/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/blog/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/blog/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/blog/rest/authors.ts +39 -0
- package/skills/wix-headless-templates/blog/rest/comments.ts +64 -0
- package/skills/wix-headless-templates/blog/rest/post-likes.ts +37 -0
- package/skills/wix-headless-templates/blog/rest/posts.ts +123 -0
- package/skills/wix-headless-templates/blog/rest/taxonomy.ts +79 -0
- package/skills/wix-headless-templates/blog/seed/SEED.md +81 -0
- package/skills/wix-headless-templates/blog/seed/read-site.mjs +33 -0
- package/skills/wix-headless-templates/blog/seed/seed-blog.mjs +337 -0
- package/skills/wix-headless-templates/bookings/INSTRUCTIONS.md +356 -0
- package/skills/wix-headless-templates/bookings/app/components/bookings/ServiceBookingView.tsx +369 -0
- package/skills/wix-headless-templates/bookings/app/components/bookings/ServicesView.tsx +193 -0
- package/skills/wix-headless-templates/bookings/app/hooks/bookings/useBookingFlow.ts +56 -0
- package/skills/wix-headless-templates/bookings/app/hooks/bookings/useServices.ts +23 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/booking-core.ts +614 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/booking-flow-store.ts +410 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/booking.ts +227 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/services-core.ts +366 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/services-store.ts +213 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/services.ts +100 -0
- package/skills/wix-headless-templates/bookings/app/wix/bookings/types.ts +236 -0
- package/skills/wix-headless-templates/bookings/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/bookings/app-astro/pages/services/[slug].astro +81 -0
- package/skills/wix-headless-templates/bookings/app-astro/pages/services.astro +40 -0
- package/skills/wix-headless-templates/bookings/project/README.md +15 -0
- package/skills/wix-headless-templates/bookings/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/bookings/project/package-lock.json +10546 -0
- package/skills/wix-headless-templates/bookings/project/package.json +41 -0
- package/skills/wix-headless-templates/bookings/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/bookings/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/bookings/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/bookings/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/bookings/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/bookings/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/bookings/project/src/components/bookings/ServiceBookingView.tsx +369 -0
- package/skills/wix-headless-templates/bookings/project/src/components/bookings/ServicesView.tsx +193 -0
- package/skills/wix-headless-templates/bookings/project/src/hooks/bookings/useBookingFlow.ts +56 -0
- package/skills/wix-headless-templates/bookings/project/src/hooks/bookings/useServices.ts +23 -0
- package/skills/wix-headless-templates/bookings/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/bookings/project/src/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/bookings/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/bookings/project/src/pages/services/[slug].astro +81 -0
- package/skills/wix-headless-templates/bookings/project/src/pages/services.astro +40 -0
- package/skills/wix-headless-templates/bookings/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/booking-core.ts +614 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/booking-flow-store.ts +410 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/booking.ts +227 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/services-core.ts +366 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/services-store.ts +213 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/services.ts +100 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/bookings/types.ts +236 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/bookings/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/bookings/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/bookings/rest/booking.ts +227 -0
- package/skills/wix-headless-templates/bookings/rest/services.ts +94 -0
- package/skills/wix-headless-templates/bookings/seed/SEED.md +109 -0
- package/skills/wix-headless-templates/bookings/seed/read-site.mjs +28 -0
- package/skills/wix-headless-templates/bookings/seed/seed-bookings.mjs +407 -0
- package/skills/wix-headless-templates/cms/INSTRUCTIONS.md +399 -0
- package/skills/wix-headless-templates/cms/app/hooks/cms/useCollection.ts +82 -0
- package/skills/wix-headless-templates/cms/app/hooks/cms/useItem.ts +37 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/collection-store.ts +220 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/collections-core.ts +41 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/collections.ts +28 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/item-store.ts +93 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/items-core.ts +259 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/items.ts +182 -0
- package/skills/wix-headless-templates/cms/app/wix/cms/types.ts +138 -0
- package/skills/wix-headless-templates/cms/app-astro/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-templates/cms/project/README.md +15 -0
- package/skills/wix-headless-templates/cms/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/cms/project/package-lock.json +9798 -0
- package/skills/wix-headless-templates/cms/project/package.json +37 -0
- package/skills/wix-headless-templates/cms/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/cms/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/cms/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/cms/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/cms/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/cms/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/cms/project/src/hooks/cms/useCollection.ts +82 -0
- package/skills/wix-headless-templates/cms/project/src/hooks/cms/useItem.ts +37 -0
- package/skills/wix-headless-templates/cms/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/cms/project/src/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-templates/cms/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/cms/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/collection-store.ts +220 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/collections-core.ts +41 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/collections.ts +28 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/item-store.ts +93 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/items-core.ts +259 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/items.ts +182 -0
- package/skills/wix-headless-templates/cms/project/src/wix/cms/types.ts +138 -0
- package/skills/wix-headless-templates/cms/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/cms/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/cms/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/cms/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/cms/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/cms/rest/collections.ts +25 -0
- package/skills/wix-headless-templates/cms/rest/items.ts +189 -0
- package/skills/wix-headless-templates/cms/seed/SEED.md +116 -0
- package/skills/wix-headless-templates/cms/seed/read-site.mjs +20 -0
- package/skills/wix-headless-templates/cms/seed/seed-cms.mjs +321 -0
- package/skills/wix-headless-templates/compose.mjs +83 -0
- package/skills/wix-headless-templates/donations/INSTRUCTIONS.md +349 -0
- package/skills/wix-headless-templates/donations/app/components/donations/DonateForm.tsx +155 -0
- package/skills/wix-headless-templates/donations/app/components/donations/DonationReceipt.tsx +46 -0
- package/skills/wix-headless-templates/donations/app/components/donations/GoalProgress.tsx +49 -0
- package/skills/wix-headless-templates/donations/app/hooks/donations/useCampaigns.ts +21 -0
- package/skills/wix-headless-templates/donations/app/hooks/donations/useDonation.ts +27 -0
- package/skills/wix-headless-templates/donations/app/hooks/donations/useDonationReceipt.ts +19 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/campaigns-store.ts +59 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/campaigns.ts +83 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/donate.ts +95 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/donation-store.ts +163 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/donations-core.ts +466 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/receipt-store.ts +55 -0
- package/skills/wix-headless-templates/donations/app/wix/donations/types.ts +121 -0
- package/skills/wix-headless-templates/donations/app-astro/components/donations/CampaignPage.astro +43 -0
- package/skills/wix-headless-templates/donations/app-astro/layouts/SiteLayout.astro +45 -0
- package/skills/wix-headless-templates/donations/app-astro/pages/donate/[id].astro +28 -0
- package/skills/wix-headless-templates/donations/app-astro/pages/donate/index.astro +51 -0
- package/skills/wix-headless-templates/donations/app-astro/pages/donate/thank-you.astro +13 -0
- package/skills/wix-headless-templates/donations/project/README.md +15 -0
- package/skills/wix-headless-templates/donations/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/donations/project/package-lock.json +10266 -0
- package/skills/wix-headless-templates/donations/project/package.json +39 -0
- package/skills/wix-headless-templates/donations/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/donations/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/donations/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/donations/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/donations/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/donations/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/donations/project/src/components/donations/CampaignPage.astro +43 -0
- package/skills/wix-headless-templates/donations/project/src/components/donations/DonateForm.tsx +155 -0
- package/skills/wix-headless-templates/donations/project/src/components/donations/DonationReceipt.tsx +46 -0
- package/skills/wix-headless-templates/donations/project/src/components/donations/GoalProgress.tsx +49 -0
- package/skills/wix-headless-templates/donations/project/src/hooks/donations/useCampaigns.ts +21 -0
- package/skills/wix-headless-templates/donations/project/src/hooks/donations/useDonation.ts +27 -0
- package/skills/wix-headless-templates/donations/project/src/hooks/donations/useDonationReceipt.ts +19 -0
- package/skills/wix-headless-templates/donations/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/donations/project/src/layouts/SiteLayout.astro +45 -0
- package/skills/wix-headless-templates/donations/project/src/pages/donate/[id].astro +28 -0
- package/skills/wix-headless-templates/donations/project/src/pages/donate/index.astro +51 -0
- package/skills/wix-headless-templates/donations/project/src/pages/donate/thank-you.astro +13 -0
- package/skills/wix-headless-templates/donations/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/donations/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/donations/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/campaigns-store.ts +59 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/campaigns.ts +83 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donate.ts +95 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donation-store.ts +163 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donations-core.ts +466 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/receipt-store.ts +55 -0
- package/skills/wix-headless-templates/donations/project/src/wix/donations/types.ts +121 -0
- package/skills/wix-headless-templates/donations/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/donations/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/donations/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/donations/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/donations/rest/campaigns.ts +76 -0
- package/skills/wix-headless-templates/donations/rest/donate.ts +90 -0
- package/skills/wix-headless-templates/donations/seed/SEED.md +90 -0
- package/skills/wix-headless-templates/donations/seed/read-site.mjs +33 -0
- package/skills/wix-headless-templates/donations/seed/seed-donations.mjs +250 -0
- package/skills/wix-headless-templates/events/INSTRUCTIONS.md +387 -0
- package/skills/wix-headless-templates/events/app/components/events/EventConfirmationView.tsx +139 -0
- package/skills/wix-headless-templates/events/app/components/events/EventRegistrationView.tsx +375 -0
- package/skills/wix-headless-templates/events/app/components/events/EventsView.tsx +134 -0
- package/skills/wix-headless-templates/events/app/hooks/events/useEventConfirmation.ts +21 -0
- package/skills/wix-headless-templates/events/app/hooks/events/useEventRegistration.ts +40 -0
- package/skills/wix-headless-templates/events/app/hooks/events/useEvents.ts +24 -0
- package/skills/wix-headless-templates/events/app/wix/events/events-core.ts +379 -0
- package/skills/wix-headless-templates/events/app/wix/events/events-store.ts +175 -0
- package/skills/wix-headless-templates/events/app/wix/events/events.ts +124 -0
- package/skills/wix-headless-templates/events/app/wix/events/order-store.ts +143 -0
- package/skills/wix-headless-templates/events/app/wix/events/orders-core.ts +86 -0
- package/skills/wix-headless-templates/events/app/wix/events/orders.ts +30 -0
- package/skills/wix-headless-templates/events/app/wix/events/registration-core.ts +415 -0
- package/skills/wix-headless-templates/events/app/wix/events/registration-store.ts +237 -0
- package/skills/wix-headless-templates/events/app/wix/events/registration.ts +109 -0
- package/skills/wix-headless-templates/events/app/wix/events/types.ts +249 -0
- package/skills/wix-headless-templates/events/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/events/app-astro/pages/event-confirmation.astro +12 -0
- package/skills/wix-headless-templates/events/app-astro/pages/events/[slug].astro +104 -0
- package/skills/wix-headless-templates/events/app-astro/pages/events.astro +23 -0
- package/skills/wix-headless-templates/events/project/README.md +15 -0
- package/skills/wix-headless-templates/events/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/events/project/package-lock.json +10497 -0
- package/skills/wix-headless-templates/events/project/package.json +39 -0
- package/skills/wix-headless-templates/events/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/events/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/events/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/events/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/events/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/events/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/events/project/src/components/events/EventConfirmationView.tsx +139 -0
- package/skills/wix-headless-templates/events/project/src/components/events/EventRegistrationView.tsx +375 -0
- package/skills/wix-headless-templates/events/project/src/components/events/EventsView.tsx +134 -0
- package/skills/wix-headless-templates/events/project/src/hooks/events/useEventConfirmation.ts +21 -0
- package/skills/wix-headless-templates/events/project/src/hooks/events/useEventRegistration.ts +40 -0
- package/skills/wix-headless-templates/events/project/src/hooks/events/useEvents.ts +24 -0
- package/skills/wix-headless-templates/events/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/events/project/src/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/events/project/src/pages/event-confirmation.astro +12 -0
- package/skills/wix-headless-templates/events/project/src/pages/events/[slug].astro +104 -0
- package/skills/wix-headless-templates/events/project/src/pages/events.astro +23 -0
- package/skills/wix-headless-templates/events/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/events/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/events/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/events-core.ts +379 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/events-store.ts +175 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/events.ts +124 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/order-store.ts +143 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/orders-core.ts +86 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/orders.ts +30 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/registration-core.ts +415 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/registration-store.ts +237 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/registration.ts +109 -0
- package/skills/wix-headless-templates/events/project/src/wix/events/types.ts +249 -0
- package/skills/wix-headless-templates/events/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/events/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/events/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/events/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/events/rest/events.ts +112 -0
- package/skills/wix-headless-templates/events/rest/orders.ts +28 -0
- package/skills/wix-headless-templates/events/rest/registration.ts +96 -0
- package/skills/wix-headless-templates/events/seed/SEED.md +115 -0
- package/skills/wix-headless-templates/events/seed/read-site.mjs +26 -0
- package/skills/wix-headless-templates/events/seed/seed-events.mjs +322 -0
- package/skills/wix-headless-templates/faq/INSTRUCTIONS.md +317 -0
- package/skills/wix-headless-templates/faq/app/components/faq/FaqAccordion.tsx +159 -0
- package/skills/wix-headless-templates/faq/app/components/faq/FaqCategoryNav.tsx +46 -0
- package/skills/wix-headless-templates/faq/app/components/faq/FaqSearch.tsx +56 -0
- package/skills/wix-headless-templates/faq/app/hooks/faq/useFaq.ts +53 -0
- package/skills/wix-headless-templates/faq/app/wix/faq/faq-core.ts +428 -0
- package/skills/wix-headless-templates/faq/app/wix/faq/faq-store.ts +212 -0
- package/skills/wix-headless-templates/faq/app/wix/faq/faq.ts +72 -0
- package/skills/wix-headless-templates/faq/app/wix/faq/types.ts +63 -0
- package/skills/wix-headless-templates/faq/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/faq/app-astro/pages/faq.astro +39 -0
- package/skills/wix-headless-templates/faq/project/README.md +15 -0
- package/skills/wix-headless-templates/faq/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/faq/project/package-lock.json +8837 -0
- package/skills/wix-headless-templates/faq/project/package.json +37 -0
- package/skills/wix-headless-templates/faq/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/faq/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/faq/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/faq/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/faq/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/faq/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/faq/project/src/components/faq/FaqAccordion.tsx +159 -0
- package/skills/wix-headless-templates/faq/project/src/components/faq/FaqCategoryNav.tsx +46 -0
- package/skills/wix-headless-templates/faq/project/src/components/faq/FaqSearch.tsx +56 -0
- package/skills/wix-headless-templates/faq/project/src/hooks/faq/useFaq.ts +53 -0
- package/skills/wix-headless-templates/faq/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/faq/project/src/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/faq/project/src/pages/faq.astro +39 -0
- package/skills/wix-headless-templates/faq/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/faq/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/faq/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/faq/project/src/wix/faq/faq-core.ts +428 -0
- package/skills/wix-headless-templates/faq/project/src/wix/faq/faq-store.ts +212 -0
- package/skills/wix-headless-templates/faq/project/src/wix/faq/faq.ts +72 -0
- package/skills/wix-headless-templates/faq/project/src/wix/faq/types.ts +63 -0
- package/skills/wix-headless-templates/faq/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/faq/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/faq/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/faq/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/faq/rest/faq.ts +71 -0
- package/skills/wix-headless-templates/faq/seed/SEED.md +104 -0
- package/skills/wix-headless-templates/faq/seed/read-site.mjs +23 -0
- package/skills/wix-headless-templates/faq/seed/seed-faq.mjs +302 -0
- package/skills/wix-headless-templates/forms/INSTRUCTIONS.md +417 -0
- package/skills/wix-headless-templates/forms/app/hooks/forms/useWixForm.ts +108 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/address-templates.generated.ts +13 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/form-store.ts +533 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/forms-core.ts +671 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/forms.ts +57 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/submissions-core.ts +423 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/submissions.ts +95 -0
- package/skills/wix-headless-templates/forms/app/wix/forms/types.ts +284 -0
- package/skills/wix-headless-templates/forms/project/README.md +15 -0
- package/skills/wix-headless-templates/forms/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/forms/project/package-lock.json +9102 -0
- package/skills/wix-headless-templates/forms/project/package.json +37 -0
- package/skills/wix-headless-templates/forms/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/forms/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/forms/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/forms/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/forms/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/forms/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/forms/project/src/hooks/forms/useWixForm.ts +108 -0
- package/skills/wix-headless-templates/forms/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/forms/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/forms/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/forms/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/address-templates.generated.ts +13 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/form-store.ts +533 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/forms-core.ts +671 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/forms.ts +57 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/submissions-core.ts +423 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/submissions.ts +95 -0
- package/skills/wix-headless-templates/forms/project/src/wix/forms/types.ts +284 -0
- package/skills/wix-headless-templates/forms/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/forms/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/forms/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/forms/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/forms/rest/forms.ts +37 -0
- package/skills/wix-headless-templates/forms/rest/submissions.ts +83 -0
- package/skills/wix-headless-templates/forms/seed/SEED.md +225 -0
- package/skills/wix-headless-templates/forms/seed/read-site.mjs +53 -0
- package/skills/wix-headless-templates/forms/seed/seed-forms.mjs +574 -0
- package/skills/wix-headless-templates/forms/tooling/address-templates.mjs +96 -0
- package/skills/wix-headless-templates/members/INSTRUCTIONS.md +345 -0
- package/skills/wix-headless-templates/members/app/components/members/AccountPage.tsx +16 -0
- package/skills/wix-headless-templates/members/app/components/members/AccountView.tsx +60 -0
- package/skills/wix-headless-templates/members/app/components/members/LoginForm.tsx +165 -0
- package/skills/wix-headless-templates/members/app/components/members/MemberMenu.tsx +78 -0
- package/skills/wix-headless-templates/members/app/components/members/RequireAuth.tsx +47 -0
- package/skills/wix-headless-templates/members/app/hooks/members/useMember.ts +67 -0
- package/skills/wix-headless-templates/members/app/wix/members/auth-core.ts +160 -0
- package/skills/wix-headless-templates/members/app/wix/members/auth.ts +117 -0
- package/skills/wix-headless-templates/members/app/wix/members/client.ts +27 -0
- package/skills/wix-headless-templates/members/app/wix/members/member-store.ts +133 -0
- package/skills/wix-headless-templates/members/app/wix/members/members-core.ts +43 -0
- package/skills/wix-headless-templates/members/app/wix/members/members.ts +29 -0
- package/skills/wix-headless-templates/members/app/wix/members/types.ts +21 -0
- package/skills/wix-headless-templates/members/app-astro/layouts/SiteLayout.astro +42 -0
- package/skills/wix-headless-templates/members/app-astro/pages/account.astro +9 -0
- package/skills/wix-headless-templates/members/app-astro/pages/login.astro +11 -0
- package/skills/wix-headless-templates/members/project/README.md +15 -0
- package/skills/wix-headless-templates/members/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/members/project/package-lock.json +8892 -0
- package/skills/wix-headless-templates/members/project/package.json +37 -0
- package/skills/wix-headless-templates/members/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/members/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/members/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/members/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/members/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/members/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/members/project/src/components/members/AccountPage.tsx +16 -0
- package/skills/wix-headless-templates/members/project/src/components/members/AccountView.tsx +60 -0
- package/skills/wix-headless-templates/members/project/src/components/members/LoginForm.tsx +165 -0
- package/skills/wix-headless-templates/members/project/src/components/members/MemberMenu.tsx +78 -0
- package/skills/wix-headless-templates/members/project/src/components/members/RequireAuth.tsx +47 -0
- package/skills/wix-headless-templates/members/project/src/hooks/members/useMember.ts +67 -0
- package/skills/wix-headless-templates/members/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/members/project/src/layouts/SiteLayout.astro +42 -0
- package/skills/wix-headless-templates/members/project/src/pages/account.astro +9 -0
- package/skills/wix-headless-templates/members/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/members/project/src/pages/login.astro +11 -0
- package/skills/wix-headless-templates/members/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/members/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/members/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/auth-core.ts +160 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/auth.ts +117 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/client.ts +27 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/member-store.ts +133 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/members-core.ts +43 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/members.ts +29 -0
- package/skills/wix-headless-templates/members/project/src/wix/members/types.ts +21 -0
- package/skills/wix-headless-templates/members/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/members/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/members/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/members/rest/auth.ts +224 -0
- package/skills/wix-headless-templates/members/rest/members.ts +26 -0
- package/skills/wix-headless-templates/members/seed/SEED.md +39 -0
- package/skills/wix-headless-templates/members/seed/read-site.mjs +15 -0
- package/skills/wix-headless-templates/members/seed/seed-members.mjs +91 -0
- package/skills/wix-headless-templates/portfolio/INSTRUCTIONS.md +315 -0
- package/skills/wix-headless-templates/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
- package/skills/wix-headless-templates/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
- package/skills/wix-headless-templates/portfolio/app/components/portfolio/GalleryMedia.tsx +35 -0
- package/skills/wix-headless-templates/portfolio/app/components/portfolio/ProjectDetailView.tsx +85 -0
- package/skills/wix-headless-templates/portfolio/app/hooks/portfolio/useCollectionProjects.ts +32 -0
- package/skills/wix-headless-templates/portfolio/app/hooks/portfolio/useCollections.ts +21 -0
- package/skills/wix-headless-templates/portfolio/app/hooks/portfolio/useProjectDetail.ts +31 -0
- package/skills/wix-headless-templates/portfolio/app/wix/portfolio/collection-projects-store.ts +82 -0
- package/skills/wix-headless-templates/portfolio/app/wix/portfolio/collections-store.ts +58 -0
- package/skills/wix-headless-templates/portfolio/app/wix/portfolio/portfolio-core.ts +177 -0
- package/skills/wix-headless-templates/portfolio/app/wix/portfolio/portfolio.ts +78 -0
- package/skills/wix-headless-templates/portfolio/app/wix/portfolio/project-detail-store.ts +81 -0
- package/skills/wix-headless-templates/portfolio/app/wix/portfolio/types.ts +55 -0
- package/skills/wix-headless-templates/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
- package/skills/wix-headless-templates/portfolio/app-astro/pages/portfolio.astro +21 -0
- package/skills/wix-headless-templates/portfolio/app-astro/pages/projects/[slug].astro +29 -0
- package/skills/wix-headless-templates/portfolio/project/README.md +15 -0
- package/skills/wix-headless-templates/portfolio/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/portfolio/project/package-lock.json +8760 -0
- package/skills/wix-headless-templates/portfolio/project/package.json +37 -0
- package/skills/wix-headless-templates/portfolio/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/portfolio/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/portfolio/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/portfolio/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/portfolio/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/portfolio/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/portfolio/project/src/components/portfolio/CollectionProjectsView.tsx +110 -0
- package/skills/wix-headless-templates/portfolio/project/src/components/portfolio/CollectionsView.tsx +90 -0
- package/skills/wix-headless-templates/portfolio/project/src/components/portfolio/GalleryMedia.tsx +35 -0
- package/skills/wix-headless-templates/portfolio/project/src/components/portfolio/ProjectDetailView.tsx +85 -0
- package/skills/wix-headless-templates/portfolio/project/src/hooks/portfolio/useCollectionProjects.ts +32 -0
- package/skills/wix-headless-templates/portfolio/project/src/hooks/portfolio/useCollections.ts +21 -0
- package/skills/wix-headless-templates/portfolio/project/src/hooks/portfolio/useProjectDetail.ts +31 -0
- package/skills/wix-headless-templates/portfolio/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/portfolio/project/src/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/portfolio/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/portfolio/project/src/pages/portfolio/[slug].astro +30 -0
- package/skills/wix-headless-templates/portfolio/project/src/pages/portfolio.astro +21 -0
- package/skills/wix-headless-templates/portfolio/project/src/pages/projects/[slug].astro +29 -0
- package/skills/wix-headless-templates/portfolio/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/portfolio/collection-projects-store.ts +82 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/portfolio/collections-store.ts +58 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/portfolio/portfolio-core.ts +177 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/portfolio/portfolio.ts +78 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/portfolio/project-detail-store.ts +81 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/portfolio/types.ts +55 -0
- package/skills/wix-headless-templates/portfolio/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/portfolio/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/portfolio/rest/portfolio.ts +75 -0
- package/skills/wix-headless-templates/portfolio/seed/SEED.md +86 -0
- package/skills/wix-headless-templates/portfolio/seed/read-site.mjs +20 -0
- package/skills/wix-headless-templates/portfolio/seed/seed-portfolio.mjs +253 -0
- package/skills/wix-headless-templates/pricing-plans/INSTRUCTIONS.md +376 -0
- package/skills/wix-headless-templates/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +54 -0
- package/skills/wix-headless-templates/pricing-plans/app/components/pricing-plans/PlansView.tsx +108 -0
- package/skills/wix-headless-templates/pricing-plans/app/components/pricing-plans/RequirePlan.tsx +87 -0
- package/skills/wix-headless-templates/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +41 -0
- package/skills/wix-headless-templates/pricing-plans/app/hooks/pricing-plans/usePlanAccess.ts +31 -0
- package/skills/wix-headless-templates/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +16 -0
- package/skills/wix-headless-templates/pricing-plans/app/hooks/pricing-plans/usePlans.ts +22 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plan-access-core.ts +29 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plan-access-store.ts +92 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plan-access.ts +37 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +54 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plans-core.ts +212 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plans-store.ts +64 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plans.ts +54 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/purchase-core.ts +43 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/purchase.ts +22 -0
- package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/types.ts +52 -0
- package/skills/wix-headless-templates/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-templates/pricing-plans/app-astro/pages/plans/[slug].astro +43 -0
- package/skills/wix-headless-templates/pricing-plans/app-astro/pages/plans.astro +21 -0
- package/skills/wix-headless-templates/pricing-plans/project/README.md +15 -0
- package/skills/wix-headless-templates/pricing-plans/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/pricing-plans/project/package-lock.json +9799 -0
- package/skills/wix-headless-templates/pricing-plans/project/package.json +38 -0
- package/skills/wix-headless-templates/pricing-plans/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/components/pricing-plans/PlanDetailView.tsx +54 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/components/pricing-plans/PlansView.tsx +108 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/components/pricing-plans/RequirePlan.tsx +87 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/components/pricing-plans/SubscribeButton.tsx +41 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/hooks/pricing-plans/usePlanAccess.ts +31 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/hooks/pricing-plans/usePlanPurchase.ts +16 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/hooks/pricing-plans/usePlans.ts +22 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/pages/plans/[slug].astro +43 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/pages/plans.astro +21 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plan-access-core.ts +29 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plan-access-store.ts +92 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plan-access.ts +37 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plan-purchase-store.ts +54 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plans-core.ts +212 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plans-store.ts +64 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plans.ts +54 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/purchase-core.ts +43 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/purchase.ts +22 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/types.ts +52 -0
- package/skills/wix-headless-templates/pricing-plans/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/pricing-plans/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/pricing-plans/rest/plan-access.ts +31 -0
- package/skills/wix-headless-templates/pricing-plans/rest/plans.ts +58 -0
- package/skills/wix-headless-templates/pricing-plans/rest/purchase.ts +20 -0
- package/skills/wix-headless-templates/pricing-plans/seed/SEED.md +93 -0
- package/skills/wix-headless-templates/pricing-plans/seed/read-site.mjs +22 -0
- package/skills/wix-headless-templates/pricing-plans/seed/seed-pricing-plans.mjs +301 -0
- package/skills/wix-headless-templates/rentals/INSTRUCTIONS.md +309 -0
- package/skills/wix-headless-templates/rentals/app/components/rentals/RentalBookingView.tsx +195 -0
- package/skills/wix-headless-templates/rentals/app/components/rentals/RentalsView.tsx +89 -0
- package/skills/wix-headless-templates/rentals/app/hooks/rentals/useRentalFlow.ts +31 -0
- package/skills/wix-headless-templates/rentals/app/hooks/rentals/useRentals.ts +23 -0
- package/skills/wix-headless-templates/rentals/app/wix/rentals/rental-flow-store.ts +283 -0
- package/skills/wix-headless-templates/rentals/app/wix/rentals/rentals-core.ts +435 -0
- package/skills/wix-headless-templates/rentals/app/wix/rentals/rentals-store.ts +112 -0
- package/skills/wix-headless-templates/rentals/app/wix/rentals/rentals.ts +173 -0
- package/skills/wix-headless-templates/rentals/app/wix/rentals/types.ts +113 -0
- package/skills/wix-headless-templates/rentals/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/rentals/app-astro/pages/rentals/[slug].astro +81 -0
- package/skills/wix-headless-templates/rentals/app-astro/pages/rentals.astro +24 -0
- package/skills/wix-headless-templates/rentals/project/README.md +15 -0
- package/skills/wix-headless-templates/rentals/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/rentals/project/package-lock.json +10545 -0
- package/skills/wix-headless-templates/rentals/project/package.json +40 -0
- package/skills/wix-headless-templates/rentals/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/rentals/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/rentals/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/rentals/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/rentals/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/rentals/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/rentals/project/src/components/rentals/RentalBookingView.tsx +195 -0
- package/skills/wix-headless-templates/rentals/project/src/components/rentals/RentalsView.tsx +89 -0
- package/skills/wix-headless-templates/rentals/project/src/hooks/rentals/useRentalFlow.ts +31 -0
- package/skills/wix-headless-templates/rentals/project/src/hooks/rentals/useRentals.ts +23 -0
- package/skills/wix-headless-templates/rentals/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/rentals/project/src/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-templates/rentals/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/rentals/project/src/pages/rentals/[slug].astro +81 -0
- package/skills/wix-headless-templates/rentals/project/src/pages/rentals.astro +24 -0
- package/skills/wix-headless-templates/rentals/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/rentals/rental-flow-store.ts +283 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/rentals/rentals-core.ts +435 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/rentals/rentals-store.ts +112 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/rentals/rentals.ts +173 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/rentals/types.ts +113 -0
- package/skills/wix-headless-templates/rentals/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/rentals/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/rentals/rest/rentals.ts +153 -0
- package/skills/wix-headless-templates/rentals/seed/SEED.md +95 -0
- package/skills/wix-headless-templates/rentals/seed/read-site.mjs +34 -0
- package/skills/wix-headless-templates/rentals/seed/seed-rentals.mjs +321 -0
- package/skills/wix-headless-templates/restaurants/INSTRUCTIONS.md +468 -0
- package/skills/wix-headless-templates/restaurants/app/components/restaurants/MenuView.tsx +257 -0
- package/skills/wix-headless-templates/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
- package/skills/wix-headless-templates/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
- package/skills/wix-headless-templates/restaurants/app/components/restaurants/ReservationView.tsx +212 -0
- package/skills/wix-headless-templates/restaurants/app/hooks/restaurants/useMenus.ts +34 -0
- package/skills/wix-headless-templates/restaurants/app/hooks/restaurants/useOrderCart.ts +52 -0
- package/skills/wix-headless-templates/restaurants/app/hooks/restaurants/useReservation.ts +49 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/menu-core.ts +333 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/menu-store.ts +89 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/menu.ts +109 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/order-store.ts +141 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/ordering-core.ts +287 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/ordering.ts +237 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/reservation-store.ts +279 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/reservations-core.ts +218 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/reservations.ts +109 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/time-core.ts +118 -0
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/types.ts +337 -0
- package/skills/wix-headless-templates/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
- package/skills/wix-headless-templates/restaurants/app-astro/pages/menu.astro +22 -0
- package/skills/wix-headless-templates/restaurants/app-astro/pages/reservations.astro +12 -0
- package/skills/wix-headless-templates/restaurants/project/README.md +15 -0
- package/skills/wix-headless-templates/restaurants/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/restaurants/project/package-lock.json +11038 -0
- package/skills/wix-headless-templates/restaurants/project/package.json +40 -0
- package/skills/wix-headless-templates/restaurants/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/restaurants/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/restaurants/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/restaurants/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/restaurants/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/restaurants/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/restaurants/project/src/components/restaurants/MenuView.tsx +257 -0
- package/skills/wix-headless-templates/restaurants/project/src/components/restaurants/OrderCartButton.tsx +26 -0
- package/skills/wix-headless-templates/restaurants/project/src/components/restaurants/OrderCartDrawer.tsx +121 -0
- package/skills/wix-headless-templates/restaurants/project/src/components/restaurants/ReservationView.tsx +212 -0
- package/skills/wix-headless-templates/restaurants/project/src/hooks/restaurants/useMenus.ts +34 -0
- package/skills/wix-headless-templates/restaurants/project/src/hooks/restaurants/useOrderCart.ts +52 -0
- package/skills/wix-headless-templates/restaurants/project/src/hooks/restaurants/useReservation.ts +49 -0
- package/skills/wix-headless-templates/restaurants/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/restaurants/project/src/layouts/SiteLayout.astro +47 -0
- package/skills/wix-headless-templates/restaurants/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/restaurants/project/src/pages/menu.astro +22 -0
- package/skills/wix-headless-templates/restaurants/project/src/pages/reservations.astro +12 -0
- package/skills/wix-headless-templates/restaurants/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/menu-core.ts +333 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/menu-store.ts +89 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/menu.ts +109 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/order-store.ts +141 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/ordering-core.ts +287 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/ordering.ts +237 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/reservation-store.ts +279 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/reservations-core.ts +218 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/reservations.ts +109 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/time-core.ts +118 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/types.ts +337 -0
- package/skills/wix-headless-templates/restaurants/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/restaurants/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/restaurants/rest/menu.ts +96 -0
- package/skills/wix-headless-templates/restaurants/rest/ordering.ts +222 -0
- package/skills/wix-headless-templates/restaurants/rest/reservations.ts +102 -0
- package/skills/wix-headless-templates/restaurants/seed/SEED.md +118 -0
- package/skills/wix-headless-templates/restaurants/seed/read-site.mjs +25 -0
- package/skills/wix-headless-templates/restaurants/seed/seed-restaurants.mjs +577 -0
- package/skills/wix-headless-templates/shared/CONTENT.md +22 -0
- package/skills/wix-headless-templates/shared/CUSTOM_OPERATIONS.md +100 -0
- package/skills/wix-headless-templates/shared/DESIGN.md +37 -0
- package/skills/wix-headless-templates/shared/SUPPLIED-CONTENT.md +27 -0
- package/skills/wix-headless-templates/shared/app/styles/global.css +57 -0
- package/skills/wix-headless-templates/shared/app/wix/config.ts +16 -0
- package/skills/wix-headless-templates/shared/app/wix/media.ts +106 -0
- package/skills/wix-headless-templates/shared/app/wix/money.ts +24 -0
- package/skills/wix-headless-templates/shared/app/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
- package/skills/wix-headless-templates/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +69 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/INSTRUCTIONS.md +194 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/components/site-search/SearchBox.tsx +136 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/components/site-search/SearchHit.tsx +50 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/components/site-search/SearchResults.tsx +300 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/hooks/site-search/useSearch.ts +31 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/hooks/site-search/useSuggest.ts +26 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/wix/site-search/search-core.ts +520 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/wix/site-search/search-store.ts +235 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/wix/site-search/search.ts +80 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/wix/site-search/suggest-store.ts +178 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app/wix/site-search/types.ts +158 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/app-astro/pages/search.astro +33 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/rest/search.ts +82 -0
- package/skills/wix-headless-templates/shared/capabilities/site-search/seed/install.mjs +43 -0
- package/skills/wix-headless-templates/shared/rest/client.ts +155 -0
- package/skills/wix-headless-templates/shared/rest/config.ts +4 -0
- package/skills/wix-headless-templates/shared/rest/media.ts +92 -0
- package/skills/wix-headless-templates/shared/seed/images.mjs +183 -0
- package/skills/wix-headless-templates/shared/seed/read-site.mjs +97 -0
- package/skills/wix-headless-templates/shared/seed/site-context.mjs +70 -0
- package/skills/wix-headless-templates/shared/seed/site.mjs +48 -0
- package/skills/wix-headless-templates/shared/seed/wix-cli.mjs +44 -0
- package/skills/wix-headless-templates/storefront/INSTRUCTIONS.md +685 -0
- package/skills/wix-headless-templates/storefront/app/components/storefront/CartButton.tsx +26 -0
- package/skills/wix-headless-templates/storefront/app/components/storefront/CartDrawer.tsx +239 -0
- package/skills/wix-headless-templates/storefront/app/components/storefront/FilterPanel.tsx +267 -0
- package/skills/wix-headless-templates/storefront/app/components/storefront/OptionPicker.tsx +171 -0
- package/skills/wix-headless-templates/storefront/app/components/storefront/QuickAdd.tsx +148 -0
- package/skills/wix-headless-templates/storefront/app/hooks/storefront/useCart.ts +59 -0
- package/skills/wix-headless-templates/storefront/app/hooks/storefront/useProductDetail.ts +42 -0
- package/skills/wix-headless-templates/storefront/app/hooks/storefront/useShop.ts +34 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/cart-core.ts +220 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/cart-store.ts +134 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/cart.ts +187 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/catalog-core.ts +698 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/catalog.ts +260 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/product-detail-store.ts +280 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/shop-store.ts +341 -0
- package/skills/wix-headless-templates/storefront/app/wix/storefront/types.ts +305 -0
- package/skills/wix-headless-templates/storefront/app-astro/layouts/SiteLayout.astro +65 -0
- package/skills/wix-headless-templates/storefront/project/README.md +15 -0
- package/skills/wix-headless-templates/storefront/project/astro.config.mjs +22 -0
- package/skills/wix-headless-templates/storefront/project/package-lock.json +10786 -0
- package/skills/wix-headless-templates/storefront/project/package.json +41 -0
- package/skills/wix-headless-templates/storefront/project/public/favicon.svg +9 -0
- package/skills/wix-headless-templates/storefront/project/src/assets/astro.svg +1 -0
- package/skills/wix-headless-templates/storefront/project/src/assets/background.svg +1 -0
- package/skills/wix-headless-templates/storefront/project/src/assets/wix.svg +18 -0
- package/skills/wix-headless-templates/storefront/project/src/components/Hero.astro +77 -0
- package/skills/wix-headless-templates/storefront/project/src/components/Welcome.astro +95 -0
- package/skills/wix-headless-templates/storefront/project/src/components/storefront/CartButton.tsx +26 -0
- package/skills/wix-headless-templates/storefront/project/src/components/storefront/CartDrawer.tsx +239 -0
- package/skills/wix-headless-templates/storefront/project/src/components/storefront/FilterPanel.tsx +267 -0
- package/skills/wix-headless-templates/storefront/project/src/components/storefront/OptionPicker.tsx +171 -0
- package/skills/wix-headless-templates/storefront/project/src/components/storefront/QuickAdd.tsx +148 -0
- package/skills/wix-headless-templates/storefront/project/src/hooks/storefront/useCart.ts +59 -0
- package/skills/wix-headless-templates/storefront/project/src/hooks/storefront/useProductDetail.ts +42 -0
- package/skills/wix-headless-templates/storefront/project/src/hooks/storefront/useShop.ts +34 -0
- package/skills/wix-headless-templates/storefront/project/src/layouts/Layout.astro +22 -0
- package/skills/wix-headless-templates/storefront/project/src/layouts/SiteLayout.astro +65 -0
- package/skills/wix-headless-templates/storefront/project/src/pages/index.astro +8 -0
- package/skills/wix-headless-templates/storefront/project/src/styles/global.css +57 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/config.ts +16 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/media.ts +106 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/money.ts +24 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/sdk.ts +89 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/cart-core.ts +220 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/cart-store.ts +134 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/cart.ts +187 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/catalog-core.ts +698 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/catalog.ts +260 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/product-detail-store.ts +280 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/shop-store.ts +341 -0
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/types.ts +305 -0
- package/skills/wix-headless-templates/storefront/project/tsconfig.json +5 -0
- package/skills/wix-headless-templates/storefront/rest/cart.ts +183 -0
- package/skills/wix-headless-templates/storefront/rest/catalog.ts +267 -0
- package/skills/wix-headless-templates/storefront/seed/SEED.md +169 -0
- package/skills/wix-headless-templates/storefront/seed/read-site.mjs +38 -0
- package/skills/wix-headless-templates/storefront/seed/seed-store.mjs +839 -0
- package/skills/wix-manage/SKILL.md +11 -7
- package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +1 -1
- package/skills/wix-manage/references/custom-apps/use-app-skills-and-app-tools.md +206 -0
- package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +17 -24
- package/skills/wix-manage/references/sites/create-headless-site.md +2 -0
- package/skills/wix-manage/references/sites/upload-static-site.md +262 -171
- package/skills/wix-manage/references/stores/update-product-with-options.md +1 -1
- package/skills/wix-headless/entry/bootstrap.mjs +0 -156
- package/skills/wix-headless/entry/skill.md +0 -78
- package/skills/wix-headless-kit/cold-start/bootstrap.mjs +0 -156
- package/skills/wix-headless-kit/cold-start/cold-start.md +0 -111
- package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +0 -423
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
// Storefront seed — a BUILD-TIME script, never shipped in the app. Run it from the project
|
|
2
|
+
// root (where wix.config.json lives) with a plan file:
|
|
3
|
+
//
|
|
4
|
+
// node <SKILL_ROOT>/templates/storefront/seed/seed-store.mjs plan.json
|
|
5
|
+
//
|
|
6
|
+
// It mints its own site token via the Wix CLI (the token never leaves this process), installs
|
|
7
|
+
// the Wix Stores app if needed, waits for the V3 catalog, bulk-creates products (variants
|
|
8
|
+
// expanded, descriptions converted to rich text), creates categories (serially — the shared
|
|
9
|
+
// tree 409s on concurrent creates), assigns products, and attaches images. Prints a JSON
|
|
10
|
+
// result to stdout.
|
|
11
|
+
//
|
|
12
|
+
// Plan shape (see SEED.md):
|
|
13
|
+
// { "products": [{ "name", "description", "price", "compareAtPrice"?, "quantity",
|
|
14
|
+
// "options"?: [{ "name", "type"?: "text"|"color",
|
|
15
|
+
// "choices": ["S","M"] | [{ "name", "colorCode"?, "imageUrl"? | "imagePath"? | "imagePrompt"?, "altText"? }] }],
|
|
16
|
+
// "variantPrices"?: { "<choice name>": price },
|
|
17
|
+
// "ribbon"?, "modifiers"?: [{ "name", "type"?: "choices"|"text", "mandatory"?,
|
|
18
|
+
// "choices"?: ["Gift wrap"], "maxChars"?, "minChars"? }],
|
|
19
|
+
// "infoSections"?: [{ "title", "description" }],
|
|
20
|
+
// "preorder"?: { "message"?, "limit"? },
|
|
21
|
+
// "imageUrl"? | "imagePath"? | "imagePrompt"?, "altText"?,
|
|
22
|
+
// "digitalFileUrl"? | "digitalFilePath"?, "digitalFileName"? }],
|
|
23
|
+
// "categories"?: { "<category name>": ["<product name>", ...] },
|
|
24
|
+
// "categoryDetails"?: { "<category name>": { "description"?, "imageUrl"? | "imagePath"? | "imagePrompt"? } } }
|
|
25
|
+
//
|
|
26
|
+
// Seeding is ADDITIVE — this script never deletes or overwrites existing content.
|
|
27
|
+
// If a call fails with an unexpected shape, read the live API reference (every call below
|
|
28
|
+
// carries a docs: line with its reference page) — never guess.
|
|
29
|
+
import { setSiteCurrency } from "../../shared/seed/site.mjs";
|
|
30
|
+
import { basename } from "node:path";
|
|
31
|
+
import { readFileSync } from "node:fs";
|
|
32
|
+
import { resolveItemImages } from "../../shared/seed/images.mjs";
|
|
33
|
+
import { seedSiteId } from "../../shared/seed/site-context.mjs";
|
|
34
|
+
import { wixToken } from "../../shared/seed/wix-cli.mjs";
|
|
35
|
+
|
|
36
|
+
const API = "https://www.wixapis.com";
|
|
37
|
+
const STORES_APP_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
|
|
38
|
+
|
|
39
|
+
// ---- auth: siteId from wix.config.json, token minted by the Wix CLI ----------------------------
|
|
40
|
+
|
|
41
|
+
export function makeCtx({ cwd = process.cwd() } = {}) {
|
|
42
|
+
// The content site: the config's site, or the parent on a migration preview (site-context.mjs stops
|
|
43
|
+
// a seed there unless --allow-parent is passed after the user confirmed).
|
|
44
|
+
const siteId = seedSiteId({ cwd, argv: process.argv });
|
|
45
|
+
// The CLI returns a byte-identical token within a run — mint once, reuse.
|
|
46
|
+
const token = wixToken(siteId, cwd);
|
|
47
|
+
return { token, siteId };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ---- transport ----------------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
async function req(ctx, path, { method = "POST", body } = {}) {
|
|
53
|
+
// Retry while the catalog is still provisioning: right after a fresh Stores install the V3
|
|
54
|
+
// WRITE path becomes usable later than the read path, so the first bulk-create can 428 even
|
|
55
|
+
// after the read probe clears. Wait it out (~80s budget); other errors throw immediately.
|
|
56
|
+
// ⚠️ An errored bulk create (seen live with a bare 429 {}) may still have APPLIED
|
|
57
|
+
// server-side — creation is idempotent by name in setupStore for exactly that reason.
|
|
58
|
+
for (let attempt = 0; ; attempt++) {
|
|
59
|
+
const res = await fetch(API + path, {
|
|
60
|
+
method,
|
|
61
|
+
headers: {
|
|
62
|
+
Authorization: `Bearer ${ctx.token}`,
|
|
63
|
+
"wix-site-id": ctx.siteId,
|
|
64
|
+
"Content-Type": "application/json",
|
|
65
|
+
},
|
|
66
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
67
|
+
});
|
|
68
|
+
const json = await res.json().catch(() => ({}));
|
|
69
|
+
if (res.ok) return json;
|
|
70
|
+
if (isProvisioning(res.status, json) && attempt < 40) {
|
|
71
|
+
await sleep(2000);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
79
|
+
|
|
80
|
+
// A freshly installed catalog signals "not writable yet" with a 428 under (at least) two codes.
|
|
81
|
+
const PROVISIONING_CODES = new Set(["CATALOG_V1_SITE_CALLING_CATALOG_V3_API", "CATALOG_V3_SITE_PROVISIONING"]);
|
|
82
|
+
|
|
83
|
+
function isProvisioning(status, json) {
|
|
84
|
+
if (PROVISIONING_CODES.has(json?.details?.applicationError?.code)) return true;
|
|
85
|
+
return status === 428 && /provision/i.test(json?.message || "");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/query-products.md
|
|
89
|
+
async function waitForCatalogV3(ctx, { attempts = 40, delayMs = 2000 } = {}) {
|
|
90
|
+
for (let i = 0; i < attempts; i++) {
|
|
91
|
+
const res = await fetch(`${API}/stores/v3/products/query`, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: { Authorization: `Bearer ${ctx.token}`, "wix-site-id": ctx.siteId, "Content-Type": "application/json" },
|
|
94
|
+
body: JSON.stringify({ query: { paging: { limit: 1 } } }),
|
|
95
|
+
});
|
|
96
|
+
if (res.ok) return;
|
|
97
|
+
const json = await res.json().catch(() => ({}));
|
|
98
|
+
if (!isProvisioning(res.status, json)) return;
|
|
99
|
+
await sleep(delayMs);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---- description string -> Wix rich-text nodes --------------------------------------------------
|
|
104
|
+
// Descriptions arrive as HTML as often as not. The writable field is `description` (Ricos
|
|
105
|
+
// nodes) — the HTML `plainDescription` the storefront renders is derived from them, so markup
|
|
106
|
+
// dropped into a TEXT node comes back escaped and the PDP shows literal tags. Convert the tags
|
|
107
|
+
// a model actually emits; a tag-free string stays one paragraph.
|
|
108
|
+
|
|
109
|
+
const HTML_ENTITIES = { "&": "&", "<": "<", ">": ">", """: '"', "'": "'", " ": " " };
|
|
110
|
+
|
|
111
|
+
function decodeEntities(s) {
|
|
112
|
+
return s.replace(/&(?:amp|lt|gt|quot|#39|nbsp);/g, (m) => HTML_ENTITIES[m] ?? m);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function mkTextNodes(html) {
|
|
116
|
+
const nodes = [];
|
|
117
|
+
let bold = 0, italic = 0, last = 0, m;
|
|
118
|
+
const tag = /<(\/?)(strong|b|em|i)\s*\/?>/gi;
|
|
119
|
+
const push = (raw) => {
|
|
120
|
+
const text = decodeEntities(raw.replace(/<[^>]*>/g, ""));
|
|
121
|
+
if (!text) return;
|
|
122
|
+
const decorations = [];
|
|
123
|
+
if (bold > 0) decorations.push({ type: "BOLD" });
|
|
124
|
+
if (italic > 0) decorations.push({ type: "ITALIC" });
|
|
125
|
+
nodes.push({ type: "TEXT", textData: { text, decorations } });
|
|
126
|
+
};
|
|
127
|
+
while ((m = tag.exec(html)) !== null) {
|
|
128
|
+
push(html.slice(last, m.index));
|
|
129
|
+
const step = m[1] ? -1 : 1;
|
|
130
|
+
if (/^(strong|b)$/i.test(m[2])) bold = Math.max(0, bold + step);
|
|
131
|
+
else italic = Math.max(0, italic + step);
|
|
132
|
+
last = tag.lastIndex;
|
|
133
|
+
}
|
|
134
|
+
push(html.slice(last));
|
|
135
|
+
return nodes.length ? nodes : [{ type: "TEXT", textData: { text: "", decorations: [] } }];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function mkDesc(text, i) {
|
|
139
|
+
const blocks = String(text ?? "").split(/<\/p\s*>|<br\s*\/?>/i).map((b) => b.trim()).filter(Boolean);
|
|
140
|
+
return {
|
|
141
|
+
nodes: (blocks.length ? blocks : [""]).map((block, n) => ({
|
|
142
|
+
type: "PARAGRAPH", id: `desc-${i}-${n}`,
|
|
143
|
+
nodes: mkTextNodes(block),
|
|
144
|
+
paragraphData: { textStyle: { textAlignment: "AUTO" } },
|
|
145
|
+
})),
|
|
146
|
+
metadata: { version: 1, id: `desc-meta-${i}` },
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---- options / variants -------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
function buildOptions(options = []) {
|
|
153
|
+
return options.map((o) => {
|
|
154
|
+
const color = o.type === "color";
|
|
155
|
+
return {
|
|
156
|
+
name: o.name,
|
|
157
|
+
optionRenderType: color ? "SWATCH_CHOICES" : "TEXT_CHOICES",
|
|
158
|
+
choicesSettings: {
|
|
159
|
+
choices: o.choices.map((c) =>
|
|
160
|
+
color
|
|
161
|
+
? { choiceType: "ONE_COLOR", name: c.name, colorCode: c.colorCode }
|
|
162
|
+
: { choiceType: "CHOICE_TEXT", name: typeof c === "string" ? c : c.name }),
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Modifiers collect buyer input WITHOUT creating variants (gift wrap, engraving) — defined inline
|
|
169
|
+
// like options, each becomes a customization. `type: "text"` → FREE_TEXT with the merchant's
|
|
170
|
+
// character limits; anything else → TEXT_CHOICES. `mandatory` defaults to TRUE, which is how the
|
|
171
|
+
// storefront reads an omitted flag.
|
|
172
|
+
function buildModifiers(modifiers = []) {
|
|
173
|
+
return modifiers.map((m) => {
|
|
174
|
+
const text = m.type === "text";
|
|
175
|
+
return {
|
|
176
|
+
name: m.name,
|
|
177
|
+
mandatory: m.mandatory !== false,
|
|
178
|
+
...(text
|
|
179
|
+
? {
|
|
180
|
+
modifierRenderType: "FREE_TEXT",
|
|
181
|
+
freeTextSettings: {
|
|
182
|
+
title: m.title ?? m.name,
|
|
183
|
+
...(m.maxChars ? { maxCharCount: m.maxChars } : {}),
|
|
184
|
+
...(m.minChars ? { minCharCount: m.minChars } : {}),
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
: {
|
|
188
|
+
modifierRenderType: "TEXT_CHOICES",
|
|
189
|
+
choicesSettings: {
|
|
190
|
+
choices: (m.choices ?? []).map((c) => ({
|
|
191
|
+
choiceType: "CHOICE_TEXT",
|
|
192
|
+
name: typeof c === "string" ? c : c.name,
|
|
193
|
+
...(typeof c === "object" && c.addedPrice != null ? { addedPrice: String(c.addedPrice) } : {}),
|
|
194
|
+
})),
|
|
195
|
+
},
|
|
196
|
+
}),
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Info sections (materials, shipping, care) — inline definitions; the same title on two products
|
|
202
|
+
// shares one section (uniqueName is derived from the title).
|
|
203
|
+
function buildInfoSections(sections = [], i) {
|
|
204
|
+
return sections.map((s, n) => ({
|
|
205
|
+
uniqueName: String(s.title).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 100) || `section-${n}`,
|
|
206
|
+
title: s.title,
|
|
207
|
+
description: mkDesc(s.description, `info-${i}-${n}`),
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Pre-order needs counted stock: `preorderInfo` on the inventory item, enabled with the merchant's
|
|
212
|
+
// message and the number of units buyers may pre-order once stock hits zero.
|
|
213
|
+
function preorderInfo(preorder) {
|
|
214
|
+
if (!preorder) return { enabled: false };
|
|
215
|
+
return {
|
|
216
|
+
enabled: true,
|
|
217
|
+
...(preorder.message ? { message: preorder.message } : {}),
|
|
218
|
+
...(Number.isInteger(preorder.limit) ? { limit: preorder.limit } : {}),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Full Cartesian product, each variant priced/stocked from the product; visible:true baked in.
|
|
223
|
+
// `variantPrices` prices a variant by one of its choice names ("Large": 32) — the first choice
|
|
224
|
+
// with a price wins; the product's compareAtPrice is kept only when it stays above that price.
|
|
225
|
+
function expandVariants(options = [], { price, compareAtPrice, quantity, inStock, preorder, variantPrices = {} }, digitalFileId) {
|
|
226
|
+
const priceOf = (amount) => ({
|
|
227
|
+
actualPrice: { amount: String(amount) },
|
|
228
|
+
...(compareAtPrice && Number(compareAtPrice) > Number(amount) ? { compareAtPrice: { amount: String(compareAtPrice) } } : {}),
|
|
229
|
+
});
|
|
230
|
+
const base = {
|
|
231
|
+
price: priceOf(price),
|
|
232
|
+
visible: true,
|
|
233
|
+
...(digitalFileId
|
|
234
|
+
? { digitalProperties: { digitalFile: { id: digitalFileId } }, inventoryItem: { inStock: true } }
|
|
235
|
+
// inStock:true == untracked stock — always buyable, no count. Otherwise track a quantity.
|
|
236
|
+
: { physicalProperties: {}, inventoryItem: inStock === true
|
|
237
|
+
? { inStock: true }
|
|
238
|
+
: { quantity: quantity ?? 0, preorderInfo: preorderInfo(preorder) } }),
|
|
239
|
+
};
|
|
240
|
+
if (!options.length) return [base];
|
|
241
|
+
let combos = [[]];
|
|
242
|
+
for (const o of options) {
|
|
243
|
+
const rt = o.type === "color" ? "SWATCH_CHOICES" : "TEXT_CHOICES";
|
|
244
|
+
const names = o.choices.map((c) => (typeof c === "string" ? c : c.name));
|
|
245
|
+
combos = combos.flatMap((combo) =>
|
|
246
|
+
names.map((choiceName) => [...combo, { optionChoiceNames: { optionName: o.name, choiceName, renderType: rt } }]));
|
|
247
|
+
}
|
|
248
|
+
return combos.map((choices) => {
|
|
249
|
+
const override = choices.map((c) => variantPrices[c.optionChoiceNames.choiceName]).find((v) => v != null);
|
|
250
|
+
return { ...base, choices, ...(override != null ? { price: priceOf(override) } : {}) };
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ---- operations ---------------------------------------------------------------------------------
|
|
255
|
+
|
|
256
|
+
// docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
|
|
257
|
+
export async function installStoresApp(ctx) {
|
|
258
|
+
try {
|
|
259
|
+
await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
|
|
260
|
+
tenant: { tenantType: "SITE", id: ctx.siteId },
|
|
261
|
+
appInstance: { appDefId: STORES_APP_ID, enabled: true },
|
|
262
|
+
} });
|
|
263
|
+
} catch {
|
|
264
|
+
// already installed is fine — the readiness wait below still confirms the V3 catalog is live
|
|
265
|
+
}
|
|
266
|
+
await waitForCatalogV3(ctx);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Existing products by exact name (for idempotent reruns). `name` is NOT filterable on the
|
|
270
|
+
// V3 query — fetch a page and match client-side (seed catalogs are small). Empty map on any
|
|
271
|
+
// failure — falling back to create-everything is the additive behavior we had before.
|
|
272
|
+
/** Every product in the catalog (id, name, slug, revision), cursor-paged. Throws on a failed read. */
|
|
273
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/query-products.md
|
|
274
|
+
export async function readAllProducts(ctx) {
|
|
275
|
+
const out = [];
|
|
276
|
+
let cursor;
|
|
277
|
+
do {
|
|
278
|
+
const r = await req(ctx, "/stores/v3/products/query", { body: { query: { cursorPaging: { limit: 100, ...(cursor ? { cursor } : {}) } } } });
|
|
279
|
+
for (const p of r.products ?? []) out.push({ id: p.id, name: p.name, slug: p.slug, revision: p.revision });
|
|
280
|
+
cursor = r.pagingMetadata?.cursors?.next || undefined;
|
|
281
|
+
} while (cursor);
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export async function queryProductsByNames(ctx, names, all) {
|
|
286
|
+
const out = new Map();
|
|
287
|
+
if (!names.length) return out;
|
|
288
|
+
try {
|
|
289
|
+
const wanted = new Set(names);
|
|
290
|
+
for (const p of all ?? (await readAllProducts(ctx))) {
|
|
291
|
+
if (wanted.has(p.name) && !out.has(p.name)) out.set(p.name, { id: p.id, slug: p.slug, revision: p.revision });
|
|
292
|
+
}
|
|
293
|
+
} catch (e) {
|
|
294
|
+
console.error(`product name pre-check failed (creating everything): ${String(e.message).slice(0, 120)}`);
|
|
295
|
+
}
|
|
296
|
+
return out;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// A digital variant is SELLABLE only with BOTH a file and stock: without the file the cart rejects
|
|
300
|
+
// it as ITEM_NOT_FOUND_IN_CATALOG, without stock as "exceeds available inventory" — and either way
|
|
301
|
+
// the product reads back visible and in the catalog, so nothing surfaces until a buyer tries to buy.
|
|
302
|
+
// A digitalFile* field is the only way into DIGITAL here, which makes the file-less product
|
|
303
|
+
// unbuildable. The bytes are PUT, not imported by url: an uploaded file is READY at once, while an
|
|
304
|
+
// imported one stays PENDING and the cart rejects the product until it settles.
|
|
305
|
+
// docs: https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/generate-file-upload-url.md
|
|
306
|
+
const FILE_MIME = { pdf: "application/pdf", zip: "application/zip", epub: "application/epub+zip",
|
|
307
|
+
mp3: "audio/mpeg", wav: "audio/wav", mp4: "video/mp4", png: "image/png", jpg: "image/jpeg" };
|
|
308
|
+
|
|
309
|
+
async function uploadDigitalFile(ctx, { digitalFileUrl, digitalFilePath, digitalFileName }) {
|
|
310
|
+
const src = digitalFilePath ?? digitalFileUrl;
|
|
311
|
+
const fileName = digitalFileName || decodeURIComponent(basename(new URL(src, "file:").pathname));
|
|
312
|
+
const mimeType = FILE_MIME[fileName.split(".").pop().toLowerCase()];
|
|
313
|
+
if (!mimeType) throw new Error(`digitalFileName needs one of these extensions (${Object.keys(FILE_MIME).join(", ")}): ${fileName}`);
|
|
314
|
+
const bytes = digitalFilePath
|
|
315
|
+
? readFileSync(digitalFilePath)
|
|
316
|
+
: await fetch(digitalFileUrl).then((r) => {
|
|
317
|
+
// Don't invent a file and don't ship an unbuyable DIGITAL product: seed it PHYSICAL
|
|
318
|
+
// with stock (drop digitalFileUrl/digitalFilePath, set inStock or a quantity) and
|
|
319
|
+
// tell the user the download still needs a real file.
|
|
320
|
+
if (!r.ok) throw new Error(`digitalFileUrl ${digitalFileUrl} -> ${r.status}. No fetchable file: re-seed this product as PHYSICAL with stock and tell the user it needs a real file before it can be sold as a download.`);
|
|
321
|
+
return r.arrayBuffer();
|
|
322
|
+
});
|
|
323
|
+
const { uploadUrl } = await req(ctx, "/site-media/v1/files/generate-upload-url", { body: { mimeType, fileName } });
|
|
324
|
+
const res = await fetch(uploadUrl, { method: "PUT", headers: { "Content-Type": mimeType }, body: bytes });
|
|
325
|
+
const json = await res.json().catch(() => ({}));
|
|
326
|
+
const id = (json.file || json)?.id;
|
|
327
|
+
if (!res.ok || !id) throw new Error(`digital file upload failed (${res.status}): ${JSON.stringify(json).slice(0, 200)}`);
|
|
328
|
+
return id;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/bulk-create-products-with-inventory.md
|
|
332
|
+
export async function bulkCreateProducts(ctx, products) {
|
|
333
|
+
const fileIds = await Promise.all(products.map((p) =>
|
|
334
|
+
p.digitalFileUrl || p.digitalFilePath ? uploadDigitalFile(ctx, p) : null));
|
|
335
|
+
const body = {
|
|
336
|
+
returnEntity: true,
|
|
337
|
+
products: products.map((p, i) => ({
|
|
338
|
+
name: p.name,
|
|
339
|
+
// DIGITAL drops physicalProperties and can't be POS-visible (DIGITAL_PRODUCT_CANNOT_BE_VISIBLE_IN_POS).
|
|
340
|
+
...(fileIds[i]
|
|
341
|
+
? { productType: "DIGITAL" }
|
|
342
|
+
: { productType: "PHYSICAL", physicalProperties: {}, visibleInPos: true }),
|
|
343
|
+
visible: true,
|
|
344
|
+
description: mkDesc(p.description, i),
|
|
345
|
+
options: buildOptions(p.options),
|
|
346
|
+
// ribbons, modifiers and info sections are created inline by name, like options
|
|
347
|
+
...(p.ribbon ? { ribbon: { name: p.ribbon } } : {}),
|
|
348
|
+
...(p.modifiers?.length ? { modifiers: buildModifiers(p.modifiers) } : {}),
|
|
349
|
+
...(p.infoSections?.length ? { infoSections: buildInfoSections(p.infoSections, i) } : {}),
|
|
350
|
+
variantsInfo: { variants: expandVariants(p.options, p, fileIds[i]) },
|
|
351
|
+
})),
|
|
352
|
+
};
|
|
353
|
+
const r = await req(ctx, "/stores/v3/bulk/products-with-inventory/create", { body });
|
|
354
|
+
// NB: results nest under productResults.results[].item — NOT a top-level `results`.
|
|
355
|
+
// The bulk returns 200 even on PARTIAL failure, so never map results by array position:
|
|
356
|
+
// pair each result to its input via itemMetadata.originalIndex and drop the ones that
|
|
357
|
+
// didn't persist. Positional mapping shifts every id after a failure onto the wrong
|
|
358
|
+
// product — which then mislabels categories and attaches images to the wrong items.
|
|
359
|
+
const created = [];
|
|
360
|
+
const failures = [];
|
|
361
|
+
for (const x of r.productResults?.results ?? []) {
|
|
362
|
+
const i = x.itemMetadata?.originalIndex;
|
|
363
|
+
const src = typeof i === "number" ? products[i] : undefined;
|
|
364
|
+
if (!x.itemMetadata?.success || !x.item?.id) {
|
|
365
|
+
failures.push({
|
|
366
|
+
name: src?.name,
|
|
367
|
+
error: x.itemMetadata?.error?.description ?? x.itemMetadata?.error?.code ?? "unknown",
|
|
368
|
+
});
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
created.push({
|
|
372
|
+
id: x.item.id, slug: x.item.slug, revision: x.item.revision, name: src?.name,
|
|
373
|
+
variantId: x.item.variantsInfo?.variants?.[0]?.id,
|
|
374
|
+
hasOptions: (src?.options?.length ?? 0) > 0,
|
|
375
|
+
isDigital: !!fileIds[i],
|
|
376
|
+
quantity: src?.quantity ?? 0,
|
|
377
|
+
inStock: src?.inStock,
|
|
378
|
+
preorder: src?.preorder,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
await stockOptionlessProducts(ctx, created);
|
|
382
|
+
return {
|
|
383
|
+
created: created.map((p) => ({ id: p.id, slug: p.slug, revision: p.revision, name: p.name })),
|
|
384
|
+
failures,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// The bulk create stocks a variant via its choices; an OPTION-LESS product's single default
|
|
389
|
+
// variant is NOT stocked by it and lands OUT_OF_STOCK — stock those explicitly.
|
|
390
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/query-products.md
|
|
391
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/inventory-items-v3/bulk-create-inventory-items.md
|
|
392
|
+
async function stockOptionlessProducts(ctx, created) {
|
|
393
|
+
const need = created.filter((p) => !p.hasOptions && !p.isDigital && p.id); // digital variants ship inStock from the create
|
|
394
|
+
if (!need.length) return;
|
|
395
|
+
const missing = need.filter((p) => !p.variantId).map((p) => p.id);
|
|
396
|
+
if (missing.length) {
|
|
397
|
+
const q = await req(ctx, "/stores/v3/products/query", { body: { query: { filter: { id: { $in: missing } }, paging: { limit: missing.length } } } });
|
|
398
|
+
const vById = new Map((q.products ?? []).map((p) => [p.id, p.variantsInfo?.variants?.[0]?.id]));
|
|
399
|
+
need.forEach((p) => { if (!p.variantId) p.variantId = vById.get(p.id); });
|
|
400
|
+
}
|
|
401
|
+
// inStock:true == untracked stock (always buyable, no count). Only send a quantity when the
|
|
402
|
+
// product actually tracks one, or Wix rejects the pair; pre-order rides on the counted item.
|
|
403
|
+
const inventoryItems = need
|
|
404
|
+
.filter((p) => p.variantId)
|
|
405
|
+
.map((p) => ({
|
|
406
|
+
productId: p.id,
|
|
407
|
+
variantId: p.variantId,
|
|
408
|
+
...(p.inStock === true ? { inStock: true } : { quantity: p.quantity, ...(p.preorder ? { preorderInfo: preorderInfo(p.preorder) } : {}) }),
|
|
409
|
+
}));
|
|
410
|
+
if (inventoryItems.length) {
|
|
411
|
+
await req(ctx, "/stores/v3/bulk/inventory-items/create", { body: { inventoryItems } });
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Existing categories by name (for idempotent reruns) — a re-run of the seed must reuse
|
|
416
|
+
// "Donuts", not create a second one. Empty map on any failure (falls back to create).
|
|
417
|
+
export async function queryCategoriesByNames(ctx, names) {
|
|
418
|
+
const out = new Map();
|
|
419
|
+
if (!names.length) return out;
|
|
420
|
+
try {
|
|
421
|
+
const r = await req(ctx, "/categories/v1/categories/query", {
|
|
422
|
+
body: { treeReference: { appNamespace: "@wix/stores", treeKey: null }, query: { cursorPaging: { limit: 100 } } },
|
|
423
|
+
});
|
|
424
|
+
const wanted = new Set(names);
|
|
425
|
+
for (const c of r.categories ?? []) if (wanted.has(c.name) && !out.has(c.name)) out.set(c.name, c.id);
|
|
426
|
+
} catch (e) {
|
|
427
|
+
console.error(`category name pre-check failed (creating everything): ${String(e.message).slice(0, 120)}`);
|
|
428
|
+
}
|
|
429
|
+
return out;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Categories share the @wix/stores tree revision — concurrent creates 409, so: sequential.
|
|
433
|
+
// Idempotent by name: a name that already exists is reused, never duplicated (its description
|
|
434
|
+
// and image are left as they are). `details[name]` = { description?, imageUrl? } — the image is a
|
|
435
|
+
// Wix-hosted URL (resolveItemImages) passed at create time; the API re-hosts a full URL itself.
|
|
436
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/categories/create-category.md
|
|
437
|
+
export async function createCategories(ctx, names, details = {}) {
|
|
438
|
+
const existing = await queryCategoriesByNames(ctx, names);
|
|
439
|
+
const out = [];
|
|
440
|
+
for (const name of names) {
|
|
441
|
+
if (existing.has(name)) {
|
|
442
|
+
out.push({ id: existing.get(name), name });
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
const d = details[name] ?? {};
|
|
446
|
+
const r = await req(ctx, "/categories/v1/categories", {
|
|
447
|
+
body: {
|
|
448
|
+
category: {
|
|
449
|
+
name,
|
|
450
|
+
visible: true,
|
|
451
|
+
...(d.description ? { description: String(d.description).slice(0, 600) } : {}),
|
|
452
|
+
...(d.imageUrl ? { image: { url: d.imageUrl } } : {}), // an Image OBJECT — a bare URL string is rejected
|
|
453
|
+
},
|
|
454
|
+
treeReference: { appNamespace: "@wix/stores", treeKey: null },
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
out.push({ id: r.category?.id, name });
|
|
458
|
+
}
|
|
459
|
+
return out;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/categories/bulk-add-items-to-category.md
|
|
464
|
+
export async function addProductsToCategories(ctx, mapping) {
|
|
465
|
+
for (const [categoryId, productIds] of Object.entries(mapping)) {
|
|
466
|
+
await req(ctx, `/categories/v1/bulk/categories/${categoryId}/add-items`, {
|
|
467
|
+
body: {
|
|
468
|
+
items: productIds.map((catalogItemId) => ({ catalogItemId, appId: STORES_APP_ID })),
|
|
469
|
+
treeReference: { appNamespace: "@wix/stores", treeKey: null },
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Bulk image attach in ONE call. items: [{ id, url, altText }] — no revision to pass: the
|
|
476
|
+
// current revision is read right before the update, so attach any number of times, any pass.
|
|
477
|
+
// Wix re-hosts each url server-side; the media can take a little while to appear on read-back
|
|
478
|
+
// (propagation) — normal, not a failure.
|
|
479
|
+
// The bulk update returns 200 on PARTIAL failure, like the bulk create: each item's outcome is
|
|
480
|
+
// in results[].itemMetadata (success, error, originalIndex). Seen live (runs 85 and 86,
|
|
481
|
+
// 2026-09-26): one product of three came back with no media while the call succeeded — most
|
|
482
|
+
// likely its revision moved between the read and the update (variant stocking runs just
|
|
483
|
+
// before). So: pair results to inputs, retry the misses once with fresh revisions, and report
|
|
484
|
+
// what actually persisted. Returns { attached: [id], failures: [{ id, error }] }.
|
|
485
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/bulk-update-products.md
|
|
486
|
+
// Writing `media.itemsInfo.items` REPLACES the gallery and CLEARS every choice's link into it (seen
|
|
487
|
+
// live: a re-sent gallery came back with the links empty; a gallery that drops a linked item is
|
|
488
|
+
// refused outright, "Missing media files. Products must include media files linked to choices").
|
|
489
|
+
// So the attach merges: the items already there are re-sent by id, only a url not yet in the
|
|
490
|
+
// gallery (by file name) is added, a product with nothing new is left untouched, and a product
|
|
491
|
+
// whose choices were linked (by this seed or by the owner in the dashboard) gets those links put
|
|
492
|
+
// back right after.
|
|
493
|
+
const sameFile = (a, b) => a && b && basename(a) === basename(b);
|
|
494
|
+
const galleryHas = (items, url) => items.some((it) => sameFile(it.image?.filename, url) || sameFile(it.image?.url, url));
|
|
495
|
+
|
|
496
|
+
export async function attachProductImages(ctx, items) {
|
|
497
|
+
if (!items?.length) return { attached: [], failures: [] };
|
|
498
|
+
const send = async (batch) => {
|
|
499
|
+
const ids = batch.map((it) => it.id);
|
|
500
|
+
const q = await req(ctx, "/stores/v3/products/query", {
|
|
501
|
+
body: { query: { filter: { id: { $in: ids } }, paging: { limit: ids.length } }, fields: ["MEDIA_ITEMS_INFO", "PRODUCT_CHOICES_MEDIA_REFERENCES", "VARIANT_OPTION_CHOICE_NAMES"] },
|
|
502
|
+
});
|
|
503
|
+
const byId = new Map((q.products ?? []).map((p) => [p.id, p]));
|
|
504
|
+
const ok = new Set();
|
|
505
|
+
const failed = [];
|
|
506
|
+
const toSend = [];
|
|
507
|
+
for (const it of batch) {
|
|
508
|
+
const p = byId.get(it.id);
|
|
509
|
+
const current = p?.media?.itemsInfo?.items ?? [];
|
|
510
|
+
const wanted = it.images ?? [{ url: it.url, altText: it.altText }];
|
|
511
|
+
const fresh = wanted.filter(({ url }) => !galleryHas(current, url));
|
|
512
|
+
if (!fresh.length) { ok.add(it.id); continue; } // every image is already there
|
|
513
|
+
toSend.push({ it, p, items: [...current.map(({ id }) => ({ id })), ...fresh.map(({ url, altText }) => ({ url, altText }))] });
|
|
514
|
+
}
|
|
515
|
+
if (toSend.length) {
|
|
516
|
+
const r = await req(ctx, "/stores/v3/bulk/products/update", {
|
|
517
|
+
body: { products: toSend.map(({ it, p, items }) => ({ product: { id: it.id, revision: p?.revision, media: { itemsInfo: { items } } } })) },
|
|
518
|
+
});
|
|
519
|
+
for (const x of r.results ?? []) {
|
|
520
|
+
const src = toSend[x.itemMetadata?.originalIndex];
|
|
521
|
+
if (!src) continue;
|
|
522
|
+
if (x.itemMetadata?.success) ok.add(src.it.id);
|
|
523
|
+
else failed.push({ id: src.it.id, error: x.itemMetadata?.error?.description ?? x.itemMetadata?.error?.code ?? "unknown" });
|
|
524
|
+
}
|
|
525
|
+
// the gallery write cleared the choice links: put back the ones the product had
|
|
526
|
+
for (const { it, p } of toSend) {
|
|
527
|
+
if (!ok.has(it.id)) continue;
|
|
528
|
+
const links = choiceLinksOf(p);
|
|
529
|
+
if (links.length) await linkChoiceImages(ctx, it.id, links).catch((e) => failed.push({ id: it.id, error: `relink: ${e?.message ?? e}` }));
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// an input with no result at all did not persist either
|
|
533
|
+
for (const it of batch) if (!ok.has(it.id) && !failed.some((f) => f.id === it.id)) failed.push({ id: it.id, error: "no result for item" });
|
|
534
|
+
return { ok, failed };
|
|
535
|
+
};
|
|
536
|
+
const first = await send(items);
|
|
537
|
+
const attached = new Set(first.ok);
|
|
538
|
+
let failures = first.failed;
|
|
539
|
+
if (failures.length) {
|
|
540
|
+
const retry = await send(items.filter((it) => failures.some((f) => f.id === it.id)));
|
|
541
|
+
for (const id of retry.ok) attached.add(id);
|
|
542
|
+
failures = retry.failed;
|
|
543
|
+
}
|
|
544
|
+
return { attached: [...attached], failures };
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// The choice → gallery-item links a product carries (read with PRODUCT_CHOICES_MEDIA_REFERENCES).
|
|
548
|
+
function choiceLinksOf(p) {
|
|
549
|
+
const out = [];
|
|
550
|
+
for (const o of p?.options ?? []) {
|
|
551
|
+
for (const c of o.choicesSettings?.choices ?? []) {
|
|
552
|
+
const mediaId = c.media?.items?.[0]?.mediaId;
|
|
553
|
+
if (mediaId) out.push({ optionName: o.name, choiceName: c.name, mediaId });
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return out;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Per-choice images (the dashboard's "image per colour"): a choice points at an item of the
|
|
560
|
+
// product's OWN gallery, so the image is attached to the gallery first (pass 2) and linked here by
|
|
561
|
+
// the gallery item's id — the id of the uploaded file is a different id and 400s. Links are a
|
|
562
|
+
// product update, which the API only accepts with the variants re-sent beside the options, so the
|
|
563
|
+
// current variants (id, choices, price) ride along unchanged. Wix derives a variant's own media
|
|
564
|
+
// from its choice at creation only; the storefront reads the choice's image, so a link made here
|
|
565
|
+
// shows up on the product page the same as one made in the dashboard.
|
|
566
|
+
// docs: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/update-product.md
|
|
567
|
+
// `links`: [{ optionName, choiceName, url }] (the file attached in pass 2) or [{ …, mediaId }] (a
|
|
568
|
+
// gallery item id, used to put the owner's links back after a gallery write).
|
|
569
|
+
export async function linkChoiceImages(ctx, productId, links) {
|
|
570
|
+
const read = () => req(ctx, `/stores/v3/products/${productId}?fields=MEDIA_ITEMS_INFO&fields=VARIANT_OPTION_CHOICE_NAMES`, { method: "GET" });
|
|
571
|
+
let { product: p } = await read();
|
|
572
|
+
const galleryIdFor = (link) => {
|
|
573
|
+
const items = p?.media?.itemsInfo?.items ?? [];
|
|
574
|
+
if (link.mediaId) return items.some((it) => it.id === link.mediaId) ? link.mediaId : null;
|
|
575
|
+
const hit = items.find((it) => sameFile(it.image?.filename, link.url) || sameFile(it.image?.url, link.url));
|
|
576
|
+
return hit?.id ?? null;
|
|
577
|
+
};
|
|
578
|
+
// the gallery can lag the attach (propagation, seen past 6 s live): poll for up to half a minute
|
|
579
|
+
for (let i = 0; i < 5 && links.some((l) => !galleryIdFor(l)); i++) {
|
|
580
|
+
await new Promise((r) => setTimeout(r, 6000));
|
|
581
|
+
({ product: p } = await read());
|
|
582
|
+
}
|
|
583
|
+
const missing = [];
|
|
584
|
+
const options = (p?.options ?? []).map((o) => ({
|
|
585
|
+
id: o.id,
|
|
586
|
+
name: o.name,
|
|
587
|
+
optionRenderType: o.optionRenderType,
|
|
588
|
+
choicesSettings: {
|
|
589
|
+
choices: (o.choicesSettings?.choices ?? []).map((c) => {
|
|
590
|
+
const link = links.find((l) => l.optionName === o.name && l.choiceName === c.name);
|
|
591
|
+
const mediaId = link ? galleryIdFor(link) : null;
|
|
592
|
+
if (link && !mediaId) missing.push(`${o.name} / ${c.name}`);
|
|
593
|
+
return {
|
|
594
|
+
choiceId: c.choiceId,
|
|
595
|
+
name: c.name,
|
|
596
|
+
choiceType: c.choiceType,
|
|
597
|
+
...(c.colorCode ? { colorCode: c.colorCode } : {}),
|
|
598
|
+
...(mediaId ? { media: { items: [{ mediaId }] } } : {}),
|
|
599
|
+
};
|
|
600
|
+
}),
|
|
601
|
+
},
|
|
602
|
+
}));
|
|
603
|
+
const physical = p?.productType !== "DIGITAL";
|
|
604
|
+
const variants = (p?.variantsInfo?.variants ?? []).map((v) => ({
|
|
605
|
+
id: v.id,
|
|
606
|
+
choices: v.choices,
|
|
607
|
+
price: {
|
|
608
|
+
actualPrice: { amount: v.price?.actualPrice?.amount },
|
|
609
|
+
...(v.price?.compareAtPrice?.amount ? { compareAtPrice: { amount: v.price.compareAtPrice.amount } } : {}),
|
|
610
|
+
},
|
|
611
|
+
visible: v.visible !== false,
|
|
612
|
+
...(physical ? { physicalProperties: {} } : {}),
|
|
613
|
+
}));
|
|
614
|
+
if (missing.length < links.length) {
|
|
615
|
+
await req(ctx, `/stores/v3/products/${productId}`, {
|
|
616
|
+
method: "PATCH",
|
|
617
|
+
body: { product: { id: productId, revision: p.revision, options, variantsInfo: { variants } } },
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
return { linked: links.length - missing.length, missing };
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Reject plans the API would reject halfway through, while nothing has been created yet —
|
|
624
|
+
// a mid-batch 400 leaves a half-seeded store that the agent then has to reason about.
|
|
625
|
+
export function validateProducts(products) {
|
|
626
|
+
const problems = [];
|
|
627
|
+
const colorByName = new Map();
|
|
628
|
+
products.forEach((p, i) => {
|
|
629
|
+
const where = p.name ? `"${p.name}"` : `product #${i + 1}`;
|
|
630
|
+
if (!p.name) problems.push(`${where}: name is required`);
|
|
631
|
+
if (p.quantity != null && (!Number.isInteger(p.quantity) || p.quantity < 0)) {
|
|
632
|
+
problems.push(`${where}: quantity must be a non-negative integer (got ${p.quantity}) — omit it and set inStock:true for untracked stock`);
|
|
633
|
+
}
|
|
634
|
+
if (p.preorder && (p.inStock === true || p.digitalFilePath || p.digitalFileUrl)) {
|
|
635
|
+
problems.push(`${where}: preorder needs counted stock (a quantity) on a physical product`);
|
|
636
|
+
}
|
|
637
|
+
if (p.preorder?.limit != null && (!Number.isInteger(p.preorder.limit) || p.preorder.limit < 1)) {
|
|
638
|
+
problems.push(`${where}: preorder.limit must be a positive integer`);
|
|
639
|
+
}
|
|
640
|
+
for (const m of p.modifiers ?? []) {
|
|
641
|
+
if (!m?.name) problems.push(`${where}: every modifier needs a name`);
|
|
642
|
+
else if (m.type !== "text" && !(m.choices?.length > 0)) problems.push(`${where}: modifier "${m.name}" needs choices (or type: "text")`);
|
|
643
|
+
}
|
|
644
|
+
for (const s of p.infoSections ?? []) if (!s?.title) problems.push(`${where}: every info section needs a title`);
|
|
645
|
+
const choiceNames = new Set((p.options ?? []).flatMap((o) => (o.choices ?? []).map((c) => (typeof c === "string" ? c : c?.name))));
|
|
646
|
+
for (const [choice, amount] of Object.entries(p.variantPrices ?? {})) {
|
|
647
|
+
if (!choiceNames.has(choice)) problems.push(`${where}: variantPrices names "${choice}", which is not a choice of its options`);
|
|
648
|
+
if (!(Number(amount) >= 0)) problems.push(`${where}: variantPrices["${choice}"] must be a non-negative number`);
|
|
649
|
+
}
|
|
650
|
+
for (const opt of p.options ?? []) {
|
|
651
|
+
const seen = new Set();
|
|
652
|
+
for (const c of opt.choices ?? []) {
|
|
653
|
+
const key = typeof c === "string" ? c : c?.name;
|
|
654
|
+
if (seen.has(key)) problems.push(`${where}: option "${opt.name}" repeats the choice "${key}"`);
|
|
655
|
+
seen.add(key);
|
|
656
|
+
// Wix keys a color choice by name, so the same name with two codes collides.
|
|
657
|
+
const code = typeof c === "object" ? c?.colorCode : undefined;
|
|
658
|
+
if (code) {
|
|
659
|
+
const prev = colorByName.get(key);
|
|
660
|
+
if (prev && prev !== code) problems.push(`color "${key}" is ${prev} on one product and ${code} on another — pick one`);
|
|
661
|
+
colorByName.set(key, code);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
if (problems.length) throw new Error(`invalid seed plan:\n - ${problems.join("\n - ")}`);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* ONE-CALL seed: install → currency → create products → categories → attach images, ids
|
|
671
|
+
* threaded in memory. This is the default path — call it once instead of the individual
|
|
672
|
+
* functions.
|
|
673
|
+
*/
|
|
674
|
+
export async function setupStore(ctx, { products = [], categories = {}, categoryDetails = {}, currency } = {}) {
|
|
675
|
+
validateProducts(products);
|
|
676
|
+
await installStoresApp(ctx);
|
|
677
|
+
// Before any product exists: a product's price is stored in the site currency at create time,
|
|
678
|
+
// so switching afterwards leaves the catalog priced in the old one.
|
|
679
|
+
if (currency) await setSiteCurrency(ctx, currency);
|
|
680
|
+
|
|
681
|
+
// What the catalog held BEFORE this seed and the plan does not name: on a fresh install that is
|
|
682
|
+
// Wix's sample catalog ("Baseball Cap", "Ceramic Flower Vase", a dozen of them), which the live shop
|
|
683
|
+
// lists next to the owner's products. Reported (`preexisting`), never touched: this seed deletes
|
|
684
|
+
// nothing on a site, ever. The owner removes what they do not want in the dashboard; the closing
|
|
685
|
+
// message tells them it is there and where.
|
|
686
|
+
const planNames = new Set(products.map((p) => p.name));
|
|
687
|
+
let all = [];
|
|
688
|
+
try { all = await readAllProducts(ctx); } catch (e) { console.error(`catalog read failed (skipping the pre-existing check): ${String(e.message).slice(0, 120)}`); }
|
|
689
|
+
const preexisting = all.filter((p) => !planNames.has(p.name));
|
|
690
|
+
|
|
691
|
+
// Idempotent by name: an errored bulk create (429/5xx) may still have applied server-side,
|
|
692
|
+
// and SKILL.md tells the agent to re-run a failed seed — creating only the names that don't
|
|
693
|
+
// exist yet makes that rerun safe instead of a duplicator.
|
|
694
|
+
const existing = await queryProductsByNames(ctx, products.map((p) => p.name), all.length ? all : undefined);
|
|
695
|
+
const toCreate = products.filter((p) => !existing.has(p.name));
|
|
696
|
+
const { created, failures } = toCreate.length
|
|
697
|
+
? await bulkCreateProducts(ctx, toCreate)
|
|
698
|
+
: { created: [], failures: [] };
|
|
699
|
+
const createdByName = new Map(created.map((p) => [p.name, p]));
|
|
700
|
+
const withNames = products.map((p) => {
|
|
701
|
+
const hit = createdByName.get(p.name) ?? existing.get(p.name);
|
|
702
|
+
return { ...(hit ?? {}), name: p.name };
|
|
703
|
+
});
|
|
704
|
+
const idByName = new Map(withNames.map((p) => [p.name, p.id]));
|
|
705
|
+
|
|
706
|
+
// Category images resolve before the categories exist (the create call takes the image URL);
|
|
707
|
+
// a failed image leaves the category text-only, like a product.
|
|
708
|
+
const names = Object.keys(categories);
|
|
709
|
+
const details = {};
|
|
710
|
+
if (names.length) {
|
|
711
|
+
const catFiles = await resolveItemImages(ctx, names.map((n) => ({
|
|
712
|
+
url: categoryDetails[n]?.imageUrl,
|
|
713
|
+
path: categoryDetails[n]?.imagePath,
|
|
714
|
+
prompt: categoryDetails[n]?.imagePrompt,
|
|
715
|
+
displayName: `${n.toLowerCase().replace(/[^a-z0-9]+/g, "-")}.png`,
|
|
716
|
+
})));
|
|
717
|
+
names.forEach((n, i) => {
|
|
718
|
+
details[n] = { description: categoryDetails[n]?.description, imageUrl: catFiles[i]?.url };
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
const cats = names.length ? await createCategories(ctx, names, details) : [];
|
|
722
|
+
if (cats.length) {
|
|
723
|
+
const mapping = {};
|
|
724
|
+
for (const c of cats) {
|
|
725
|
+
const ids = (categories[c.name] || []).map((n) => idByName.get(n)).filter(Boolean);
|
|
726
|
+
if (ids.length) mapping[c.id] = ids;
|
|
727
|
+
}
|
|
728
|
+
if (Object.keys(mapping).length) await addProductsToCategories(ctx, mapping);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// Pass 2 — images: resolve (import by url / generate by prompt) in one parallel wave, then
|
|
732
|
+
// bulk-attach. Failures leave the product text-only; the seed's exit never depends on images.
|
|
733
|
+
// A choice's image (`options[].choices[].imageUrl|imagePath|imagePrompt`) resolves in the same
|
|
734
|
+
// wave and joins the product's gallery; pass 3 links it to its choice.
|
|
735
|
+
const choiceSpecs = products.map((pl, i) =>
|
|
736
|
+
(pl.options ?? []).flatMap((o) =>
|
|
737
|
+
(o.choices ?? [])
|
|
738
|
+
.filter((c) => typeof c === "object" && c && (c.imageUrl || c.imagePath || c.imagePrompt))
|
|
739
|
+
.map((c) => ({
|
|
740
|
+
optionName: o.name,
|
|
741
|
+
choiceName: c.name,
|
|
742
|
+
altText: c.altText ?? `${pl.name} — ${c.name}`,
|
|
743
|
+
spec: { url: c.imageUrl, path: c.imagePath, prompt: c.imagePrompt, displayName: `${withNames[i].slug || "product"}-${String(c.name).toLowerCase().replace(/[^a-z0-9]+/g, "-")}.png` },
|
|
744
|
+
})),
|
|
745
|
+
));
|
|
746
|
+
const flatChoiceSpecs = choiceSpecs.flat();
|
|
747
|
+
const files = await resolveItemImages(ctx, [
|
|
748
|
+
...withNames.map((p, i) => ({
|
|
749
|
+
url: products[i]?.imageUrl,
|
|
750
|
+
path: products[i]?.imagePath,
|
|
751
|
+
prompt: products[i]?.imagePrompt,
|
|
752
|
+
displayName: `${p.slug || "product"}.png`,
|
|
753
|
+
})),
|
|
754
|
+
...flatChoiceSpecs.map((c) => c.spec),
|
|
755
|
+
]);
|
|
756
|
+
const choiceFiles = files.slice(withNames.length);
|
|
757
|
+
let cursor = 0;
|
|
758
|
+
const choiceLinks = choiceSpecs.map((specs) =>
|
|
759
|
+
specs.map((c) => ({ ...c, file: choiceFiles[cursor++] })).filter((c) => c.file));
|
|
760
|
+
// `p.id` guards this: a product that failed to create has no id, and bulk-updating an
|
|
761
|
+
// undefined id would 400 the whole batch and cost every other product its image.
|
|
762
|
+
const imageItems = withNames
|
|
763
|
+
.map((p, i) => {
|
|
764
|
+
if (!p.id) return null;
|
|
765
|
+
const images = [
|
|
766
|
+
...(files[i] ? [{ url: files[i].url, altText: products[i]?.altText ?? p.slug }] : []),
|
|
767
|
+
...choiceLinks[i].map((c) => ({ url: c.file.url, altText: c.altText })),
|
|
768
|
+
];
|
|
769
|
+
return images.length ? { id: p.id, images } : null;
|
|
770
|
+
})
|
|
771
|
+
.filter(Boolean);
|
|
772
|
+
// imagesAttached counts the attaches the API CONFIRMED (per-item results), not the ones sent;
|
|
773
|
+
// imageFailures names the products left text-only and why. Neither blocks the seed: a re-run of
|
|
774
|
+
// the same plan reuses the products and attaches again.
|
|
775
|
+
let imagesAttached = 0;
|
|
776
|
+
const imageFailures = [];
|
|
777
|
+
const nameOf = (id) => withNames.find((p) => p.id === id)?.name;
|
|
778
|
+
try {
|
|
779
|
+
if (imageItems.length) {
|
|
780
|
+
const r = await attachProductImages(ctx, imageItems);
|
|
781
|
+
imagesAttached = r.attached.length;
|
|
782
|
+
for (const f of r.failures) imageFailures.push({ name: nameOf(f.id), error: f.error });
|
|
783
|
+
}
|
|
784
|
+
} catch (e) {
|
|
785
|
+
for (const it of imageItems) imageFailures.push({ name: nameOf(it.id), error: e?.message ?? String(e) });
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Pass 3 — link each choice's image to its choice, by the gallery item's id.
|
|
789
|
+
let choiceImagesLinked = 0;
|
|
790
|
+
const choiceImageFailures = [];
|
|
791
|
+
for (const [i, p] of withNames.entries()) {
|
|
792
|
+
const links = choiceLinks[i];
|
|
793
|
+
if (!links.length || !p.id || !imagesAttached) continue;
|
|
794
|
+
try {
|
|
795
|
+
const r = await linkChoiceImages(ctx, p.id, links.map((c) => ({ optionName: c.optionName, choiceName: c.choiceName, url: c.file.url })));
|
|
796
|
+
choiceImagesLinked += r.linked;
|
|
797
|
+
for (const m of r.missing) choiceImageFailures.push({ name: p.name, choice: m, error: "image not in the product gallery" });
|
|
798
|
+
} catch (e) {
|
|
799
|
+
choiceImageFailures.push({ name: p.name, error: e?.message ?? String(e) });
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// failures is part of the result, not an exception: a partial seed still leaves a usable
|
|
804
|
+
// store, and the agent needs the names to report rather than silently shipping a short
|
|
805
|
+
// catalog. Re-run the seed to retry them — existing names are skipped, not duplicated.
|
|
806
|
+
return {
|
|
807
|
+
products: withNames,
|
|
808
|
+
categories: cats,
|
|
809
|
+
imagesAttached,
|
|
810
|
+
imageFailures,
|
|
811
|
+
choiceImagesLinked,
|
|
812
|
+
choiceImageFailures,
|
|
813
|
+
failures,
|
|
814
|
+
// Products the plan did not name (Wix's install samples on a fresh site, or the owner's own on an
|
|
815
|
+
// existing one): the closing message names what the shop lists and where the owner removes it.
|
|
816
|
+
preexisting: preexisting.map((p) => ({ id: p.id, name: p.name, slug: p.slug })),
|
|
817
|
+
// the Stores app's slug + products list (registered dashboard route); `store/products` is no route
|
|
818
|
+
dashboardProductsUrl: `https://manage.wix.com/dashboard/${ctx.siteId}/wix-stores/products`,
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// ---- CLI entry ----------------------------------------------------------------------------------
|
|
823
|
+
|
|
824
|
+
const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
|
|
825
|
+
if (invokedDirectly) {
|
|
826
|
+
const planPath = process.argv[2];
|
|
827
|
+
if (!planPath) {
|
|
828
|
+
console.error("usage: node seed-store.mjs <plan.json> (run from the project root)");
|
|
829
|
+
process.exit(1);
|
|
830
|
+
}
|
|
831
|
+
const plan = JSON.parse(readFileSync(planPath, "utf8"));
|
|
832
|
+
const ctx = makeCtx();
|
|
833
|
+
setupStore(ctx, plan)
|
|
834
|
+
.then((result) => console.log(JSON.stringify(result, null, 2)))
|
|
835
|
+
.catch((e) => {
|
|
836
|
+
console.error(e.message);
|
|
837
|
+
process.exit(1);
|
|
838
|
+
});
|
|
839
|
+
}
|