@jay-framework/wix-stores 0.19.7 → 0.21.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/dist/index.js CHANGED
@@ -1,12 +1,9 @@
1
1
  import { WIX_CART_CONTEXT, WIX_CART_SERVICE, cartIndicator, cartPage, provideWixCartContext, provideWixCartService } from "@jay-framework/wix-cart";
2
2
  import { createJayService, makeJayQuery, ActionError, RenderPipeline, makeJayStackComponent, makeJayInit, makeContractGenerator } from "@jay-framework/fullstack-component";
3
- import { customizationsV3, inventoryItemsV3, productsV3 } from "@wix/stores";
4
- import { categories } from "@wix/categories";
5
3
  import { registerService, getService } from "@jay-framework/stack-server-runtime";
6
- import { schemas } from "@wix/data-extension-schema";
4
+ import { wixFetch, WIX_CLIENT_SERVICE } from "@jay-framework/wix-server-client";
7
5
  import { createJayContext } from "@jay-framework/runtime";
8
6
  import "@jay-framework/component";
9
- import { WIX_CLIENT_SERVICE } from "@jay-framework/wix-server-client";
10
7
  import * as fs from "fs";
11
8
  import * as path from "path";
12
9
  import * as yaml from "js-yaml";
@@ -25,48 +22,72 @@ var CurrentSort = /* @__PURE__ */ ((CurrentSort2) => {
25
22
  CurrentSort2[CurrentSort2["nameDesc"] = 5] = "nameDesc";
26
23
  return CurrentSort2;
27
24
  })(CurrentSort || {});
28
- const instances = {
29
- productsV3ClientInstance: void 0,
30
- categoriesClientInstance: void 0,
31
- inventoryV3ClientInstance: void 0,
32
- customizationsV3ClientInstance: void 0
33
- };
34
- function getProductsV3Client(wixClient) {
35
- if (!instances.productsV3ClientInstance) {
36
- instances.productsV3ClientInstance = wixClient.use(productsV3);
25
+ function normalizeCategory(cat) {
26
+ if (!cat) return cat;
27
+ const normalized = { ...cat };
28
+ if (normalized.id && !normalized._id) {
29
+ normalized._id = normalized.id;
30
+ }
31
+ const parentCategory = normalized.parentCategory;
32
+ if (parentCategory?.id && !parentCategory?._id) {
33
+ normalized.parentCategory = { ...parentCategory, _id: parentCategory.id };
34
+ }
35
+ return normalized;
36
+ }
37
+ async function queryCategories(client, options) {
38
+ const result = await wixFetch(
39
+ client,
40
+ "/categories/v1/categories/query",
41
+ {
42
+ method: "POST",
43
+ body: {
44
+ query: {
45
+ filter: options?.filter,
46
+ sort: options?.sort,
47
+ cursorPaging: options?.cursorPaging || { limit: 100 }
48
+ },
49
+ treeReference: options?.treeReference || { appNamespace: "@wix/stores" }
50
+ }
51
+ }
52
+ );
53
+ if (result.categories) {
54
+ result.categories = result.categories.map(
55
+ (c) => normalizeCategory(c)
56
+ );
37
57
  }
38
- return instances.productsV3ClientInstance;
58
+ return result;
39
59
  }
40
- function getCategoriesClient(wixClient) {
41
- if (!instances.categoriesClientInstance) {
42
- instances.categoriesClientInstance = wixClient.use(categories);
43
- }
44
- return instances.categoriesClientInstance;
60
+ async function queryCustomizations(client, options) {
61
+ return wixFetch(client, "/stores/v3/customizations/query", {
62
+ method: "POST",
63
+ body: {
64
+ query: {
65
+ filter: options?.filter,
66
+ paging: options?.paging
67
+ }
68
+ }
69
+ });
45
70
  }
46
- function getInventoryClient(wixClient) {
47
- if (!instances.inventoryV3ClientInstance) {
48
- instances.inventoryV3ClientInstance = wixClient.use(inventoryItemsV3);
49
- }
50
- return instances.inventoryV3ClientInstance;
71
+ async function querySchemas(client, options) {
72
+ const namespace = options?.filter?.namespace || "";
73
+ const params = namespace ? `?fqdn=${encodeURIComponent(namespace)}` : "";
74
+ return wixFetch(client, `/schema-service/v1/schemas${params}`, {
75
+ method: "GET"
76
+ });
51
77
  }
52
- function getCustomizationsV3Client(wixClient) {
53
- if (!instances.customizationsV3ClientInstance) {
54
- instances.customizationsV3ClientInstance = wixClient.use(customizationsV3);
55
- }
56
- return instances.customizationsV3ClientInstance;
78
+ async function getAllProductsCategory(client) {
79
+ return wixFetch(client, "/stores/v3/all-products-category", {
80
+ method: "GET"
81
+ });
57
82
  }
58
83
  const WIX_STORES_SERVICE_MARKER = createJayService("Wix Store Service");
59
84
  function provideWixStoresService(wixClient, options) {
60
85
  let cachedTree = null;
61
86
  let cachedCustomizations = null;
62
87
  let cachedExtensionSchemas = null;
63
- const categoriesClient = getCategoriesClient(wixClient);
64
- const customizationsClient = getCustomizationsV3Client(wixClient);
88
+ let cachedAllProductsCategoryId;
65
89
  const service = {
66
- products: getProductsV3Client(wixClient),
67
- categories: categoriesClient,
68
- inventory: getInventoryClient(wixClient),
69
- customizations: customizationsClient,
90
+ wixClient,
70
91
  urls: options?.urls ?? { product: "/products/{slug}", category: null },
71
92
  defaultCategory: options?.defaultCategory ?? null,
72
93
  async getCategoryTree() {
@@ -91,11 +112,16 @@ function provideWixStoresService(wixClient, options) {
91
112
  }
92
113
  }
93
114
  };
94
- let result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("visible", true).limit(100).find();
95
- processItems(result.items || []);
96
- while (result.hasNext()) {
97
- result = await result.next();
98
- processItems(result.items || []);
115
+ let cursor;
116
+ let hasMore = true;
117
+ while (hasMore) {
118
+ const result = await queryCategories(
119
+ wixClient,
120
+ cursor ? { cursorPaging: { cursor } } : { filter: { visible: true }, cursorPaging: { limit: 100 } }
121
+ );
122
+ processItems(result.categories || []);
123
+ cursor = result.pagingMetadata?.cursors?.next;
124
+ hasMore = !!cursor;
99
125
  }
100
126
  } catch (error) {
101
127
  console.error("[wix-stores] Failed to build category tree:", error);
@@ -106,8 +132,11 @@ function provideWixStoresService(wixClient, options) {
106
132
  async getCustomizations() {
107
133
  if (cachedCustomizations) return cachedCustomizations;
108
134
  try {
109
- const result = await customizationsClient.queryCustomizations().eq("customizationType", "PRODUCT_OPTION").limit(100).find();
110
- cachedCustomizations = result.items || [];
135
+ const result = await queryCustomizations(wixClient, {
136
+ filter: { customizationType: "PRODUCT_OPTION" },
137
+ paging: { limit: 100 }
138
+ });
139
+ cachedCustomizations = result.customizations || [];
111
140
  } catch (error) {
112
141
  console.error("[wix-stores] Failed to load customizations:", error);
113
142
  cachedCustomizations = [];
@@ -117,10 +146,9 @@ function provideWixStoresService(wixClient, options) {
117
146
  async getDataExtensionSchemas() {
118
147
  if (cachedExtensionSchemas) return cachedExtensionSchemas;
119
148
  try {
120
- const client = wixClient.use(schemas);
121
- const result = await client.listDataExtensionSchemas(
122
- "wix.stores.catalog.v3.product"
123
- );
149
+ const result = await querySchemas(wixClient, {
150
+ filter: { namespace: "wix.stores.catalog.v3.product" }
151
+ });
124
152
  cachedExtensionSchemas = result?.dataExtensionSchemas ?? [];
125
153
  const fieldCount = cachedExtensionSchemas.reduce(
126
154
  (n, s) => n + Object.keys(s.jsonSchema?.properties ?? {}).length,
@@ -134,6 +162,17 @@ function provideWixStoresService(wixClient, options) {
134
162
  cachedExtensionSchemas = [];
135
163
  }
136
164
  return cachedExtensionSchemas;
165
+ },
166
+ async getAllProductsCategoryId() {
167
+ if (cachedAllProductsCategoryId !== void 0) return cachedAllProductsCategoryId;
168
+ try {
169
+ const result = await getAllProductsCategory(wixClient);
170
+ cachedAllProductsCategoryId = result.categoryId ?? null;
171
+ } catch (error) {
172
+ console.error("[wix-stores] Failed to get All Products category:", error);
173
+ cachedAllProductsCategoryId = null;
174
+ }
175
+ return cachedAllProductsCategoryId;
137
176
  }
138
177
  };
139
178
  registerService(WIX_STORES_SERVICE_MARKER, service);
@@ -178,6 +217,9 @@ var ChoiceType$1 = /* @__PURE__ */ ((ChoiceType2) => {
178
217
  ChoiceType2[ChoiceType2["ONE_COLOR"] = 1] = "ONE_COLOR";
179
218
  return ChoiceType2;
180
219
  })(ChoiceType$1 || {});
220
+ function stripWixMediaResize(url) {
221
+ return url.replace(/\/v1\/(?:fit|fill|crop)\/[^/]+\/file\.\w+$/, "");
222
+ }
181
223
  function parseWixMediaUrl(url) {
182
224
  if (!url) return null;
183
225
  const match = url.match(
@@ -214,7 +256,7 @@ function formatWixMediaUrl(_id, url, resize) {
214
256
  }
215
257
  }
216
258
  if ((url == null ? void 0 : url.startsWith("http://")) || (url == null ? void 0 : url.startsWith("https://"))) {
217
- return url;
259
+ return stripWixMediaResize(url) + resizeFragment;
218
260
  }
219
261
  if (_id) {
220
262
  return `https://static.wixstatic.com/media/${_id}${resizeFragment}`;
@@ -456,6 +498,220 @@ function mapProductToCard(product, urls, tree) {
456
498
  ...mapQuickAddOptions(product)
457
499
  };
458
500
  }
501
+ function raw(value) {
502
+ return value;
503
+ }
504
+ function rawArray(value) {
505
+ return value;
506
+ }
507
+ function str(value) {
508
+ return value;
509
+ }
510
+ function normalizeProduct(product) {
511
+ if (!product) return product;
512
+ const normalized = { ...product };
513
+ if (normalized.id && !normalized._id) {
514
+ normalized._id = normalized.id;
515
+ }
516
+ const media = raw(normalized.media);
517
+ if (media?.main) {
518
+ const main = raw(media.main);
519
+ const mainImage = raw(main.image);
520
+ normalized.media = {
521
+ ...media,
522
+ main: {
523
+ _id: main.id || main._id,
524
+ url: mainImage?.url || main.url,
525
+ altText: mainImage?.altText || main.altText,
526
+ mediaType: main.mediaType,
527
+ width: mainImage?.width,
528
+ height: mainImage?.height
529
+ }
530
+ };
531
+ }
532
+ const updatedMedia = raw(normalized.media);
533
+ const itemsInfo = raw(updatedMedia?.itemsInfo);
534
+ if (itemsInfo?.items) {
535
+ itemsInfo.items = rawArray(itemsInfo.items).map((item) => {
536
+ const image = raw(item.image);
537
+ return {
538
+ _id: item.id || item._id,
539
+ url: image?.url || item.url,
540
+ altText: image?.altText || item.altText,
541
+ mediaType: item.mediaType,
542
+ width: image?.width,
543
+ height: image?.height
544
+ };
545
+ });
546
+ }
547
+ if (normalized.options) {
548
+ normalized.options = rawArray(normalized.options).map((opt) => {
549
+ const choicesSettings = raw(opt.choicesSettings);
550
+ return {
551
+ ...opt,
552
+ _id: opt.id || opt._id,
553
+ choices: choicesSettings?.choices ? rawArray(choicesSettings.choices).map((c) => {
554
+ const linkedMedia = c.linkedMedia;
555
+ const firstMedia = linkedMedia?.[0];
556
+ const firstMediaImage = firstMedia ? raw(firstMedia.image) : void 0;
557
+ return {
558
+ ...c,
559
+ _id: c.choiceId || c._id,
560
+ value: c.name || c.value,
561
+ media: firstMedia ? {
562
+ _id: firstMedia.id,
563
+ url: str(firstMediaImage?.url) || firstMedia.url,
564
+ mediaType: firstMedia.mediaType
565
+ } : void 0
566
+ };
567
+ }) : void 0
568
+ };
569
+ });
570
+ }
571
+ if (normalized.modifiers) {
572
+ normalized.modifiers = rawArray(normalized.modifiers).map((mod) => {
573
+ const choicesSettings = raw(mod.choicesSettings);
574
+ return {
575
+ ...mod,
576
+ _id: mod.id || mod._id,
577
+ choices: choicesSettings?.choices ? rawArray(choicesSettings.choices).map((c) => ({
578
+ ...c,
579
+ _id: c.choiceId || c._id,
580
+ value: c.name || c.value
581
+ })) : void 0
582
+ };
583
+ });
584
+ }
585
+ if (normalized.infoSections) {
586
+ normalized.infoSections = rawArray(normalized.infoSections).map((s) => ({
587
+ ...s,
588
+ _id: s.id || s._id
589
+ }));
590
+ }
591
+ const variantsInfo = raw(normalized.variantsInfo);
592
+ if (variantsInfo?.variants) {
593
+ variantsInfo.variants = rawArray(variantsInfo.variants).map((v) => ({
594
+ ...v,
595
+ _id: v.id || v._id
596
+ }));
597
+ }
598
+ if (normalized.ribbon) {
599
+ const ribbon = raw(normalized.ribbon);
600
+ normalized.ribbon = {
601
+ ...ribbon,
602
+ _id: ribbon.id || ribbon._id
603
+ };
604
+ }
605
+ return normalized;
606
+ }
607
+ function normalizeProducts(products) {
608
+ return products.map(normalizeProduct);
609
+ }
610
+ async function queryProducts(client, query) {
611
+ const result = await wixFetch(client, "/stores/v3/products/query", {
612
+ method: "POST",
613
+ body: {
614
+ query: {
615
+ filter: query.filter,
616
+ sort: query.sort,
617
+ paging: query.paging
618
+ },
619
+ ...query.fields ? { fields: query.fields } : {}
620
+ }
621
+ });
622
+ if (result.products) {
623
+ result.products = normalizeProducts(result.products);
624
+ }
625
+ return result;
626
+ }
627
+ async function searchProducts$1(client, search, options) {
628
+ const result = await wixFetch(client, "/stores/v3/products/search", {
629
+ method: "POST",
630
+ body: {
631
+ search,
632
+ ...options?.fields ? { fields: options.fields } : {}
633
+ }
634
+ });
635
+ if (result.products) {
636
+ result.products = normalizeProducts(result.products);
637
+ }
638
+ return result;
639
+ }
640
+ const searchProducts$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
641
+ __proto__: null,
642
+ searchProducts: searchProducts$1
643
+ }, Symbol.toStringTag, { value: "Module" }));
644
+ async function getProduct(client, productId, options) {
645
+ const params = new URLSearchParams();
646
+ {
647
+ params.set("includeMerchantSpecificData", "true");
648
+ }
649
+ if (options?.fields) {
650
+ for (const f of options.fields) {
651
+ params.append("fields", f);
652
+ }
653
+ }
654
+ const qs = params.toString();
655
+ const result = await wixFetch(
656
+ client,
657
+ `/stores/v3/products/${productId}${qs ? "?" + qs : ""}`,
658
+ {
659
+ method: "GET"
660
+ }
661
+ );
662
+ if (result.product) {
663
+ result.product = normalizeProduct(result.product);
664
+ }
665
+ return result;
666
+ }
667
+ async function getProductBySlug$1(client, slug, options) {
668
+ const params = new URLSearchParams();
669
+ if (options?.includeMerchantSpecificData) {
670
+ params.set("includeMerchantSpecificData", "true");
671
+ }
672
+ if (options?.fields) {
673
+ for (const f of options.fields) {
674
+ params.append("fields", f);
675
+ }
676
+ }
677
+ const qs = params.toString();
678
+ const result = await wixFetch(
679
+ client,
680
+ `/stores/v3/products/slug/${slug}${qs ? "?" + qs : ""}`,
681
+ {
682
+ method: "GET"
683
+ }
684
+ );
685
+ if (result.product) {
686
+ result.product = normalizeProduct(result.product);
687
+ }
688
+ return result;
689
+ }
690
+ async function getCategory(client, categoryId) {
691
+ const result = await wixFetch(
692
+ client,
693
+ `/categories/v1/categories/${categoryId}`,
694
+ {
695
+ method: "GET"
696
+ }
697
+ );
698
+ if (result.category) {
699
+ const raw2 = result.category;
700
+ if (raw2.id && !result.category._id) {
701
+ result.category._id = raw2.id;
702
+ }
703
+ if (result.category.parentCategory) {
704
+ const rawParent = result.category.parentCategory;
705
+ if (rawParent.id && !result.category.parentCategory._id) {
706
+ result.category.parentCategory = {
707
+ ...result.category.parentCategory,
708
+ _id: rawParent.id
709
+ };
710
+ }
711
+ }
712
+ }
713
+ return result;
714
+ }
459
715
  function needsCategoryInfo(wixStores) {
460
716
  const template = wixStores.urls.product;
461
717
  return template.includes("{category}") || template.includes("{prefix}");
@@ -630,7 +886,8 @@ const searchProducts = makeJayQuery("wixStores.searchProducts").withServices(WIX
630
886
  }
631
887
  }
632
888
  ];
633
- const searchResult = await wixStores.products.searchProducts(
889
+ const searchResult = await searchProducts$1(
890
+ wixStores.wixClient,
634
891
  {
635
892
  filter,
636
893
  sort: sort.length > 0 ? sort : void 0,
@@ -719,7 +976,8 @@ const getProductBySlug = makeJayQuery("wixStores.getProductBySlug").withServices
719
976
  "CURRENCY",
720
977
  ...needsCategoryInfo(wixStores) ? ["ALL_CATEGORIES_INFO"] : []
721
978
  ];
722
- const result = await wixStores.products.getProductBySlug(slug, {
979
+ const result = await getProductBySlug$1(wixStores.wixClient, slug, {
980
+ includeMerchantSpecificData: true,
723
981
  fields: [...fields]
724
982
  });
725
983
  const product = result.product;
@@ -737,10 +995,12 @@ const getProductBySlug = makeJayQuery("wixStores.getProductBySlug").withServices
737
995
  const getVariantStock = makeJayQuery("wixStores.getVariantStock").withServices(WIX_STORES_SERVICE_MARKER).withHandler(
738
996
  async (input, wixStores) => {
739
997
  try {
740
- const product = await wixStores.products.getProduct(input.productId, {
998
+ const result = await getProduct(wixStores.wixClient, input.productId, {
999
+ includeMerchantSpecificData: true,
741
1000
  fields: ["VARIANT_OPTION_CHOICE_NAMES"]
742
1001
  });
743
- return buildVariantStockMap(product);
1002
+ if (!result.product) return {};
1003
+ return buildVariantStockMap(result.product);
744
1004
  } catch (error) {
745
1005
  console.error("[wixStores.getVariantStock] Failed:", error);
746
1006
  return {};
@@ -750,12 +1010,10 @@ const getVariantStock = makeJayQuery("wixStores.getVariantStock").withServices(W
750
1010
  const getCategories = makeJayQuery("wixStores.getCategories").withServices(WIX_STORES_SERVICE_MARKER).withCaching({ maxAge: 3600 }).withHandler(
751
1011
  async (_input, wixStores) => {
752
1012
  try {
753
- const result = await wixStores.categories.queryCategories({
754
- treeReference: {
755
- appNamespace: "@wix/stores"
756
- }
757
- }).eq("visible", true).find();
758
- return (result.items || []).map((cat) => ({
1013
+ const result = await queryCategories(wixStores.wixClient, {
1014
+ filter: { visible: true }
1015
+ });
1016
+ return (result.categories || []).map((cat) => ({
759
1017
  categoryId: cat._id || "",
760
1018
  categoryName: cat.name || ""
761
1019
  }));
@@ -877,21 +1135,25 @@ const EMPTY_CATEGORY_HEADER = {
877
1135
  breadcrumbs: [],
878
1136
  seoData: { tags: [], settings: { preventAutoRedirect: false, keywords: [] } }
879
1137
  };
880
- async function findCategoryBySlug$1(categoriesClient, slug) {
881
- const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
882
- return result.items?.[0] ?? null;
1138
+ async function findCategoryBySlug$1(wixClient, slug) {
1139
+ const result = await queryCategories(wixClient, {
1140
+ filter: { slug, visible: true },
1141
+ cursorPaging: { limit: 1 }
1142
+ });
1143
+ return result.categories?.[0] ?? null;
883
1144
  }
884
- async function loadCategoryDetails(categoriesClient, categoryId) {
1145
+ async function loadCategoryDetails(wixClient, categoryId) {
885
1146
  try {
886
- return await categoriesClient.getCategory(categoryId, { appNamespace: "@wix/stores" }, { fields: ["DESCRIPTION", "BREADCRUMBS_INFO"] });
1147
+ const result = await getCategory(wixClient, categoryId);
1148
+ return result.category ?? null;
887
1149
  } catch {
888
1150
  return null;
889
1151
  }
890
1152
  }
891
1153
  async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplate) {
892
- const details = await loadCategoryDetails(wixStoreService.categories, category._id);
1154
+ const details = await loadCategoryDetails(wixStoreService.wixClient, category._id);
893
1155
  const cat = details || category;
894
- const imageUrl = cat.image ? formatWixMediaUrl("", cat.image) : "";
1156
+ const imageUrl = cat.image?.url ? formatWixMediaUrl(cat.image.id || "", cat.image.url) : "";
895
1157
  const description = cat.description || "";
896
1158
  const categoryTree = await wixStoreService.getCategoryTree();
897
1159
  const breadcrumbs = [
@@ -941,13 +1203,13 @@ async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplat
941
1203
  seoData
942
1204
  };
943
1205
  if ((!description || !imageUrl) && cat.parentCategory?._id) {
944
- const parent = await loadCategoryDetails(wixStoreService.categories, cat.parentCategory._id);
1206
+ const parent = await loadCategoryDetails(wixStoreService.wixClient, cat.parentCategory._id);
945
1207
  if (parent) {
946
1208
  if (!header.description && parent.description) {
947
1209
  header = { ...header, description: parent.description };
948
1210
  }
949
1211
  if (!header.imageUrl) {
950
- const parentImage = parent.image ? formatWixMediaUrl("", parent.image) : "";
1212
+ const parentImage = parent.image?.url ? formatWixMediaUrl(parent.image.id || "", parent.image.url) : "";
951
1213
  if (parentImage) {
952
1214
  header = { ...header, imageUrl: parentImage, hasImage: true };
953
1215
  }
@@ -964,26 +1226,25 @@ async function renderSlowlyChanging$4(props, wixStores) {
964
1226
  let activeCategory = null;
965
1227
  let baseCategoryId = null;
966
1228
  if (categorySlug) {
967
- activeCategory = await findCategoryBySlug$1(wixStores.categories, categorySlug);
1229
+ activeCategory = await findCategoryBySlug$1(wixStores.wixClient, categorySlug);
968
1230
  baseCategoryId = activeCategory?._id ?? null;
969
1231
  } else if (prefixSlug) {
970
- activeCategory = await findCategoryBySlug$1(wixStores.categories, prefixSlug);
1232
+ activeCategory = await findCategoryBySlug$1(wixStores.wixClient, prefixSlug);
971
1233
  baseCategoryId = activeCategory?._id ?? null;
972
1234
  } else if (defaultCategorySlug) {
973
- activeCategory = await findCategoryBySlug$1(wixStores.categories, defaultCategorySlug);
1235
+ activeCategory = await findCategoryBySlug$1(wixStores.wixClient, defaultCategorySlug);
974
1236
  }
975
1237
  const tree = await wixStores.getCategoryTree();
976
1238
  const categoryHeader = activeCategory ? await buildCategoryHeader(wixStores, activeCategory, wixStores.urls.category) : EMPTY_CATEGORY_HEADER;
1239
+ const allProductsCategoryId = await wixStores.getAllProductsCategoryId();
977
1240
  return Pipeline.try(async () => {
978
- let query = wixStores.categories.queryCategories({
979
- treeReference: { appNamespace: "@wix/stores" }
980
- }).eq("visible", true);
1241
+ const categoryFilter = { visible: true };
981
1242
  if (baseCategoryId) {
982
- query = query.eq("parentCategory.id", baseCategoryId);
1243
+ categoryFilter["parentCategory.id"] = baseCategoryId;
983
1244
  }
984
1245
  const baseCategoryIds = baseCategoryId ? [baseCategoryId] : [];
985
1246
  const [categoriesResult, productsResult] = await Promise.all([
986
- query.find(),
1247
+ queryCategories(wixStores.wixClient, { filter: categoryFilter }),
987
1248
  searchProducts({
988
1249
  query: "",
989
1250
  filters: {
@@ -992,14 +1253,15 @@ async function renderSlowlyChanging$4(props, wixStores) {
992
1253
  pageSize: PAGE_SIZE
993
1254
  })
994
1255
  ]);
1256
+ const categories = (categoriesResult.categories || []).filter((cat) => cat._id !== allProductsCategoryId);
995
1257
  return {
996
- categories: categoriesResult.items || [],
1258
+ categories,
997
1259
  productsResult
998
1260
  };
999
1261
  }).recover((error) => {
1000
1262
  return handleError(error);
1001
- }).toPhaseOutput(({ categories: categories2, productsResult }) => {
1002
- const categoryInfos = categories2.map((cat) => ({
1263
+ }).toPhaseOutput(({ categories, productsResult }) => {
1264
+ const categoryInfos = categories.map((cat) => ({
1003
1265
  categoryId: cat._id || "",
1004
1266
  categoryName: cat.name || "",
1005
1267
  categorySlug: cat.slug || "",
@@ -1156,20 +1418,21 @@ async function* loadSearchParams([wixStores]) {
1156
1418
  if (rootSlug) {
1157
1419
  params.push({ prefix: rootSlug, category: node.slug });
1158
1420
  } else {
1159
- params.push({ prefix: node.slug });
1421
+ params.push({ category: node.slug });
1160
1422
  }
1161
1423
  for (const child of node.children) {
1162
1424
  collectParams(child, rootSlug ?? node.slug);
1163
1425
  }
1164
1426
  };
1427
+ const allProductsCategoryId = await wixStores.getAllProductsCategoryId();
1165
1428
  const allCategories = [];
1166
- let result = await wixStores.categories.queryCategories({
1167
- treeReference: { appNamespace: "@wix/stores" }
1168
- }).eq("visible", true).limit(100).find();
1169
- allCategories.push(...result.items || []);
1170
- while (result.hasNext()) {
1171
- result = await result.next();
1172
- allCategories.push(...result.items || []);
1429
+ let cursor;
1430
+ let hasMore = true;
1431
+ while (hasMore) {
1432
+ const result = await queryCategories(wixStores.wixClient, cursor ? { cursorPaging: { cursor } } : { filter: { visible: true }, cursorPaging: { limit: 100 } });
1433
+ allCategories.push(...result.categories || []);
1434
+ cursor = result.pagingMetadata?.cursors?.next;
1435
+ hasMore = !!cursor;
1173
1436
  }
1174
1437
  const nodeById = /* @__PURE__ */ new Map();
1175
1438
  const roots = [];
@@ -1177,6 +1440,8 @@ async function* loadSearchParams([wixStores]) {
1177
1440
  for (const cat of allCategories) {
1178
1441
  if (!cat._id)
1179
1442
  continue;
1443
+ if (cat._id === allProductsCategoryId)
1444
+ continue;
1180
1445
  const node = {
1181
1446
  slug: cat.slug || "",
1182
1447
  itemCount: cat.itemCounter ?? 0,
@@ -1206,7 +1471,7 @@ async function* loadSearchParams([wixStores]) {
1206
1471
  for (const root of roots) {
1207
1472
  sumItems(root);
1208
1473
  }
1209
- const params = [];
1474
+ const params = [{}];
1210
1475
  for (const root of roots) {
1211
1476
  collectParams(root, null);
1212
1477
  }
@@ -1259,9 +1524,9 @@ var MediaType = /* @__PURE__ */ ((MediaType2) => {
1259
1524
  return MediaType2;
1260
1525
  })(MediaType || {});
1261
1526
  function mapExtendedFields(product) {
1262
- const raw = product.extendedFields?.namespaces?.["_user_fields"] ?? {};
1527
+ const raw2 = product.extendedFields?.namespaces?.["_user_fields"] ?? {};
1263
1528
  const result = {};
1264
- for (const [key, value] of Object.entries(raw)) {
1529
+ for (const [key, value] of Object.entries(raw2)) {
1265
1530
  if (Array.isArray(value)) {
1266
1531
  result[key] = value.map((item, i) => typeof item === "object" && item !== null ? { ...item, _index: i } : { value: item, _index: i });
1267
1532
  } else {
@@ -1278,7 +1543,7 @@ async function* loadProductParams([wixStores]) {
1278
1543
  const fields = needsCategories ? ["ALL_CATEGORIES_INFO"] : [];
1279
1544
  try {
1280
1545
  const tree = needsCategories ? await wixStores.getCategoryTree() : null;
1281
- let result = await wixStores.products.queryProducts({ fields: [...fields] }).find();
1546
+ let result = await queryProducts(wixStores.wixClient, { fields: [...fields] });
1282
1547
  const mapProduct = (product) => {
1283
1548
  const slug = product.slug ?? "";
1284
1549
  if (!slug)
@@ -1294,11 +1559,7 @@ async function* loadProductParams([wixStores]) {
1294
1559
  }
1295
1560
  return params;
1296
1561
  };
1297
- yield result.items.map(mapProduct).filter((p) => p !== null);
1298
- while (result.hasNext()) {
1299
- result = await result.next();
1300
- yield result.items.map(mapProduct).filter((p) => p !== null);
1301
- }
1562
+ yield (result.products || []).map(mapProduct).filter((p) => p !== null);
1302
1563
  } catch (error) {
1303
1564
  console.error("Failed to load product slugs:", error);
1304
1565
  yield [];
@@ -1464,7 +1725,8 @@ async function renderSlowlyChanging$3(props, wixStores) {
1464
1725
  ...needsCategories ? ["ALL_CATEGORIES_INFO"] : []
1465
1726
  ];
1466
1727
  const [response, tree] = await Promise.all([
1467
- wixStores.products.getProductBySlug(props.slug, {
1728
+ getProductBySlug$1(wixStores.wixClient, props.slug, {
1729
+ includeMerchantSpecificData: true,
1468
1730
  fields: [...fields]
1469
1731
  }),
1470
1732
  wixStores.getCategoryTree()
@@ -1583,15 +1845,18 @@ async function renderSlowlyChanging$2(props, wixStores) {
1583
1845
  return { categoryName: "", products: [] };
1584
1846
  }
1585
1847
  const [categoryResult, searchResult] = await Promise.all([
1586
- wixStores.categories.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("_id", categoryId).limit(1).find().catch(() => null),
1848
+ queryCategories(wixStores.wixClient, {
1849
+ filter: { _id: categoryId },
1850
+ cursorPaging: { limit: 1 }
1851
+ }).catch(() => null),
1587
1852
  searchProducts({
1588
1853
  query: "",
1589
1854
  filters: { categoryIds: [categoryId] },
1590
1855
  pageSize: limit + 1
1591
1856
  })
1592
1857
  ]);
1593
- if (categoryResult?.items?.[0]?.name) {
1594
- categoryName = categoryResult.items[0].name;
1858
+ if (categoryResult?.categories?.[0]?.name) {
1859
+ categoryName = categoryResult.categories[0].name;
1595
1860
  }
1596
1861
  const products = searchResult.products.filter((p) => p._id !== props.productId).slice(0, limit);
1597
1862
  return { categoryName, products };
@@ -1699,34 +1964,33 @@ async function renderFastChanging(_props, carryForward, _wixStores) {
1699
1964
  });
1700
1965
  }
1701
1966
  const productSpotlight = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$1).withFastRender(renderFastChanging);
1702
- async function findCategoryBySlug(categoriesClient, slug) {
1703
- const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
1704
- return result.items?.[0] ?? null;
1967
+ async function findCategoryBySlug(wixClient, slug) {
1968
+ const result = await queryCategories(wixClient, {
1969
+ filter: { slug, visible: true },
1970
+ cursorPaging: { limit: 1 }
1971
+ });
1972
+ return result.categories?.[0] ?? null;
1705
1973
  }
1706
1974
  async function renderSlowlyChanging(props, wixStores) {
1707
1975
  const Pipeline = RenderPipeline.for();
1708
1976
  const parentCategorySlug = props.parentCategory ?? wixStores.defaultCategory;
1709
1977
  let parentCategoryId = null;
1710
1978
  if (parentCategorySlug) {
1711
- const parentCat = await findCategoryBySlug(wixStores.categories, parentCategorySlug);
1979
+ const parentCat = await findCategoryBySlug(wixStores.wixClient, parentCategorySlug);
1712
1980
  parentCategoryId = parentCat?._id ?? null;
1713
1981
  }
1714
1982
  return Pipeline.try(async () => {
1715
- let query = wixStores.categories.queryCategories({
1716
- treeReference: {
1717
- appNamespace: "@wix/stores"
1718
- }
1719
- }).eq("visible", true);
1983
+ const filter = { visible: true };
1720
1984
  if (parentCategoryId) {
1721
- query = query.eq("parentCategory.id", parentCategoryId);
1985
+ filter["parentCategory.id"] = parentCategoryId;
1722
1986
  }
1723
- const result = await query.find();
1724
- return result.items || [];
1987
+ const result = await queryCategories(wixStores.wixClient, { filter });
1988
+ return result.categories || [];
1725
1989
  }).recover((error) => {
1726
1990
  console.error("Failed to load categories:", error);
1727
1991
  return Pipeline.ok([]);
1728
- }).toPhaseOutput((categories2) => {
1729
- const categoryItems = categories2.map((cat) => ({
1992
+ }).toPhaseOutput((categories) => {
1993
+ const categoryItems = categories.map((cat) => ({
1730
1994
  _id: cat._id || "",
1731
1995
  name: cat.name || "",
1732
1996
  slug: cat.slug || "",
@@ -1756,17 +2020,17 @@ function loadWixStoresConfig(projectRoot) {
1756
2020
  return defaults;
1757
2021
  }
1758
2022
  const fileContents = fs.readFileSync(configPath, "utf8");
1759
- const raw = yaml.load(fileContents);
1760
- if (!raw) {
2023
+ const raw2 = yaml.load(fileContents);
2024
+ if (!raw2) {
1761
2025
  return defaults;
1762
2026
  }
1763
- const urls = raw.urls;
2027
+ const urls = raw2.urls;
1764
2028
  return {
1765
2029
  urls: {
1766
2030
  product: typeof urls?.product === "string" ? urls.product : defaults.urls.product,
1767
2031
  category: typeof urls?.category === "string" ? urls.category : null
1768
2032
  },
1769
- defaultCategory: typeof raw.defaultCategory === "string" ? raw.defaultCategory : null
2033
+ defaultCategory: typeof raw2.defaultCategory === "string" ? raw2.defaultCategory : null
1770
2034
  };
1771
2035
  }
1772
2036
  const init = makeJayInit().withServer(async () => {
@@ -1787,6 +2051,9 @@ const init = makeJayInit().withServer(async () => {
1787
2051
  enableClientSearch: true
1788
2052
  };
1789
2053
  });
2054
+ function wixStoresStaticContractPath(contractName) {
2055
+ return `node_modules/@jay-framework/wix-stores/dist/contracts/${contractName}.jay-contract`;
2056
+ }
1790
2057
  function flattenCategoryTree(roots, parentNames = [], parentSlugs = [], rootSlug = null, rootName = null, rootHasChildren = null) {
1791
2058
  const entries = [];
1792
2059
  for (const node of roots) {
@@ -1899,9 +2166,10 @@ function buildCategoryPrompt(config, entry) {
1899
2166
  ` category-products — pass categorySlug="${node.slug}" to show products from this category; optionally pass productId to exclude a product`,
1900
2167
  "",
1901
2168
  "Contracts:",
1902
- " agent-kit/materialized-contracts/wix-stores/product-search.jay-contract",
1903
- " agent-kit/materialized-contracts/wix-stores/category-list.jay-contract",
1904
- " agent-kit/materialized-contracts/wix-stores/category-products.jay-contract",
2169
+ ` ${wixStoresStaticContractPath("product-search")}`,
2170
+ ` ${wixStoresStaticContractPath("category-list")}`,
2171
+ ` ${wixStoresStaticContractPath("category-products")}`,
2172
+ " Related products on a product page: agent-kit/designer/related-products.md",
1905
2173
  "",
1906
2174
  "Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md."
1907
2175
  );
@@ -1932,16 +2200,39 @@ function buildCategoryAddMenuItems(roots, config) {
1932
2200
  prompt: buildCategoryPrompt(config, entry)
1933
2201
  }));
1934
2202
  }
2203
+ const PUBLIC_THUMBNAIL_ROOT = path.join("public", "aiditor-add-menu-thumbnails");
2204
+ function copyAiditorAddMenuThumbnails(ctx, resolvePackagePath, pluginName) {
2205
+ const sourceDir = resolvePackagePath(
2206
+ path.join("agent-kit", "aiditor", "thumbnails", pluginName)
2207
+ );
2208
+ if (!fs.existsSync(sourceDir)) return [];
2209
+ const destDir = path.join(ctx.projectRoot, PUBLIC_THUMBNAIL_ROOT, pluginName);
2210
+ const created = [];
2211
+ fs.mkdirSync(destDir, { recursive: true });
2212
+ for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
2213
+ if (!entry.isFile()) continue;
2214
+ const src = path.join(sourceDir, entry.name);
2215
+ const dest = path.join(destDir, entry.name);
2216
+ if (!fs.existsSync(dest) || ctx.force) {
2217
+ fs.copyFileSync(src, dest);
2218
+ created.push(path.posix.join(PUBLIC_THUMBNAIL_ROOT, pluginName, entry.name));
2219
+ }
2220
+ }
2221
+ return created;
2222
+ }
1935
2223
  const CONFIG_FILE_NAME = ".wix-stores.yaml";
1936
2224
  const ADD_MENU_OUTPUT_REL = "agent-kit/aiditor/add-menu/wix-stores.yaml";
1937
2225
  const ADD_MENU_GENERATED_REL = "agent-kit/aiditor/add-menu/wix-stores.generated.yaml";
1938
- function resolveAddMenuTemplatePath() {
2226
+ function resolvePackageAgentKitPath(relativePath) {
1939
2227
  const thisDir = path.dirname(fileURLToPath(import.meta.url));
1940
- const fromDist = path.join(thisDir, "agent-kit/aiditor/add-menu.template.yaml");
2228
+ const fromDist = path.join(thisDir, relativePath);
1941
2229
  if (fs.existsSync(fromDist)) {
1942
2230
  return fromDist;
1943
2231
  }
1944
- return path.join(thisDir, "..", "agent-kit/aiditor/add-menu.template.yaml");
2232
+ return path.join(thisDir, "..", relativePath);
2233
+ }
2234
+ function resolveAddMenuTemplatePath() {
2235
+ return resolvePackageAgentKitPath("agent-kit/aiditor/add-menu.template.yaml");
1945
2236
  }
1946
2237
  function writeAddMenuCatalog(ctx) {
1947
2238
  const outputPath = path.join(ctx.projectRoot, ADD_MENU_OUTPUT_REL);
@@ -2009,7 +2300,8 @@ async function setupWixStores(ctx) {
2009
2300
  }
2010
2301
  const service = getService(WIX_STORES_SERVICE_MARKER);
2011
2302
  try {
2012
- await service.products.searchProducts({});
2303
+ const { searchProducts: searchProductsApi } = await Promise.resolve().then(() => searchProducts$2);
2304
+ await searchProductsApi(service.wixClient, {});
2013
2305
  } catch (e) {
2014
2306
  const msg = e.message || "";
2015
2307
  const hint = msg.includes("404") || msg.includes("not found") ? "Wix Stores may not be installed on this site" : msg.includes("403") || msg.includes("permission") ? "API key may lack Wix Stores permissions" : "This package requires the Stores Catalog V3 API — if using Catalog V1, use @jay-framework/wix-stores-v1 instead";
@@ -2022,6 +2314,9 @@ async function setupWixStores(ctx) {
2022
2314
  if (addMenuCreated) {
2023
2315
  configCreated.push(addMenuCreated);
2024
2316
  }
2317
+ configCreated.push(
2318
+ ...copyAiditorAddMenuThumbnails(ctx, resolvePackageAgentKitPath, "wix-stores")
2319
+ );
2025
2320
  const message = `Wix Stores configured (product URL: ${service.urls.product})`;
2026
2321
  return {
2027
2322
  status: "configured",
@@ -2041,13 +2336,16 @@ async function generateWixStoresReferences(ctx) {
2041
2336
  }
2042
2337
  fs.mkdirSync(ctx.referencesDir, { recursive: true });
2043
2338
  const allCategories = [];
2044
- let result = await storesService.categories.queryCategories({
2045
- treeReference: { appNamespace: "@wix/stores" }
2046
- }).eq("visible", true).limit(100).find();
2047
- allCategories.push(...result.items || []);
2048
- while (result.hasNext()) {
2049
- result = await result.next();
2050
- allCategories.push(...result.items || []);
2339
+ let cursor;
2340
+ let hasMore = true;
2341
+ while (hasMore) {
2342
+ const result = await queryCategories(
2343
+ storesService.wixClient,
2344
+ cursor ? { cursorPaging: { cursor } } : { filter: { visible: true }, cursorPaging: { limit: 100 } }
2345
+ );
2346
+ allCategories.push(...result.categories || []);
2347
+ cursor = result.pagingMetadata?.cursors?.next;
2348
+ hasMore = !!cursor;
2051
2349
  }
2052
2350
  const nodeMap = /* @__PURE__ */ new Map();
2053
2351
  for (const cat of allCategories) {
@@ -2214,8 +2512,8 @@ function jsonSchemaToContractTags(properties, indent = 4) {
2214
2512
  }
2215
2513
  return tags;
2216
2514
  }
2217
- function buildExtendedFieldsSubContract(schemas2, indent = 2) {
2218
- const userFieldsSchema = schemas2.find((s) => s.namespace === "_user_fields");
2515
+ function buildExtendedFieldsSubContract(schemas, indent = 2) {
2516
+ const userFieldsSchema = schemas.find((s) => s.namespace === "_user_fields");
2219
2517
  const properties = userFieldsSchema?.jsonSchema?.properties;
2220
2518
  if (!properties || Object.keys(properties).length === 0) {
2221
2519
  return null;
@@ -2336,8 +2634,8 @@ tags:
2336
2634
 
2337
2635
  # SEO data is injected into <head> via headTags (Design Log #127), not part of the contract view state.`;
2338
2636
  const generator = makeContractGenerator().withServices(WIX_STORES_SERVICE_MARKER).generateWith(async (wixStoresService) => {
2339
- const schemas2 = await wixStoresService.getDataExtensionSchemas();
2340
- const extendedFieldsBlock = buildExtendedFieldsSubContract(schemas2);
2637
+ const schemas = await wixStoresService.getDataExtensionSchemas();
2638
+ const extendedFieldsBlock = buildExtendedFieldsSubContract(schemas);
2341
2639
  let yaml2 = BASE_CONTRACT_YAML;
2342
2640
  if (extendedFieldsBlock) {
2343
2641
  yaml2 = yaml2 + "\n\n" + extendedFieldsBlock;
@@ -2347,7 +2645,7 @@ const generator = makeContractGenerator().withServices(WIX_STORES_SERVICE_MARKER
2347
2645
  yaml: yaml2,
2348
2646
  description: "Product page with data extension fields",
2349
2647
  metadata: {
2350
- extendedFieldCount: schemas2.reduce(
2648
+ extendedFieldCount: schemas.reduce(
2351
2649
  (count, s) => count + Object.keys(s.jsonSchema?.properties ?? {}).length,
2352
2650
  0
2353
2651
  )