@jay-framework/wix-stores 0.15.6 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -149,12 +149,12 @@ src/pages/products/polgat/
149
149
 
150
150
  ### Setting Params for Static Routes
151
151
 
152
- Static route directories use `jay-params` to tell the component which category they represent:
152
+ Static route directories use `jay-params` to tell the component which prefix they represent:
153
153
 
154
154
  ```html
155
155
  <!-- src/pages/products/polgat/page.jay-html -->
156
156
  <script type="application/jay-params">
157
- category: polgat
157
+ prefix: polgat
158
158
  </script>
159
159
  <script
160
160
  type="application/jay-headless"
@@ -168,8 +168,8 @@ Static route directories use `jay-params` to tell the component which category t
168
168
 
169
169
  The category header is always loaded. The component resolves category metadata using a fallback chain:
170
170
 
171
- 1. **`subcategory` param** → load sub-category
172
- 2. **`category` / `prefix` param** → load root category
171
+ 1. **`category` param** → load category
172
+ 2. **`prefix` param** → load root category
173
173
  3. **Neither** → load `defaultCategory` from config
174
174
 
175
175
  If the resolved category is missing image, description, or SEO data, the component walks up the parent chain until it finds the data. Each field inherits independently.
@@ -2,6 +2,7 @@ name: product-page
2
2
  description: Full product detail page with variants, options, media gallery, and add-to-cart. Use for individual product pages.
3
3
  params:
4
4
  slug: string
5
+ prefix: string?
5
6
  category: string?
6
7
  tags:
7
8
  - {tag: _id, type: data, dataType: string, description: Product GUID}
@@ -184,6 +184,7 @@ import { UrlParams } from '@jay-framework/fullstack-component';
184
184
 
185
185
  export interface ProductPageParams extends UrlParams {
186
186
  slug: string;
187
+ prefix?: string;
187
188
  category?: string;
188
189
  }
189
190
 
@@ -1,15 +1,8 @@
1
1
  name: product-search
2
2
  description: Product listing with filters, sorting, and pagination. Use for search results and category pages.
3
- props:
4
- - name: category
5
- type: string
6
- description: Top-level category slug. Scopes search to this category.
7
- - name: subcategory
8
- type: string
9
- description: Sub-category slug. Further scopes within the category.
10
3
  params:
4
+ prefix: string?
11
5
  category: string?
12
- subcategory: string?
13
6
  tags:
14
7
  # Search input (matches Wix searchProducts search.search parameter)
15
8
  - tag: searchExpression
@@ -328,7 +321,7 @@ tags:
328
321
  elementType: HTMLButtonElement
329
322
  description: Button to use this suggestion
330
323
 
331
- # Category header — always populated via fallback chain (subcategorycategory → defaultCategory)
324
+ # Category header — always populated via fallback chain (categoryprefix → defaultCategory)
332
325
  - tag: categoryHeader
333
326
  type: sub-contract
334
327
  description: Active category information for the page header
@@ -254,16 +254,11 @@ export interface ProductSearchRepeatedRefs {
254
254
  }
255
255
  }
256
256
 
257
- export interface ProductSearchProps {
258
- category?: string;
259
- subcategory?: string;
260
- }
261
-
262
257
  import { UrlParams } from '@jay-framework/fullstack-component';
263
258
 
264
259
  export interface ProductSearchParams extends UrlParams {
260
+ prefix?: string;
265
261
  category?: string;
266
- subcategory?: string;
267
262
  }
268
263
 
269
- export type ProductSearchContract = JayContract<ProductSearchViewState, ProductSearchRefs, ProductSearchSlowViewState, ProductSearchFastViewState, ProductSearchInteractiveViewState, ProductSearchProps>
264
+ export type ProductSearchContract = JayContract<ProductSearchViewState, ProductSearchRefs, ProductSearchSlowViewState, ProductSearchFastViewState, ProductSearchInteractiveViewState>
package/dist/index.d.ts CHANGED
@@ -352,6 +352,11 @@ interface ProductSearchRefs {
352
352
  }
353
353
  }
354
354
 
355
+ interface ProductSearchParams extends UrlParams {
356
+ prefix?: string;
357
+ category?: string;
358
+ }
359
+
355
360
  /**
356
361
  * Configuration loader for wix-stores plugin.
357
362
  *
@@ -550,16 +555,6 @@ interface SearchProductsOutput {
550
555
  }>;
551
556
  }
552
557
 
553
- /**
554
- * URL parameters for product search routes.
555
- * Supports: category (prefix slug), subcategory (sub-category slug).
556
- */
557
- interface ProductSearchParams extends UrlParams {
558
- /** Top-level category slug (e.g., 'polgat'). Scopes search to this category. */
559
- category?: string;
560
- /** Sub-category slug (e.g., 'shirts'). Further scopes within the category. */
561
- subcategory?: string;
562
- }
563
558
  /**
564
559
  * Category info carried forward from slow to fast phase
565
560
  */
@@ -784,15 +779,12 @@ interface ProductPageRefs {
784
779
  }
785
780
  }
786
781
 
787
- /**
788
- * URL parameters for product page routes.
789
- * Supports /products/[slug] and /products/polgat/[slug] (category-prefixed).
790
- */
791
782
  interface ProductPageParams extends UrlParams {
792
- slug: string;
793
- /** Category prefix from static route (e.g., 'polgat'). Undefined for unprefixed routes. */
794
- category?: string;
783
+ slug: string;
784
+ prefix?: string;
785
+ category?: string;
795
786
  }
787
+
796
788
  interface InteractiveVariant {
797
789
  _id: string;
798
790
  sku: string;
package/dist/index.js CHANGED
@@ -920,17 +920,17 @@ async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplat
920
920
  }
921
921
  async function renderSlowlyChanging$2(props, wixStores) {
922
922
  const Pipeline = RenderPipeline.for();
923
- const subcategorySlug = props.subcategory ?? null;
924
923
  const categorySlug = props.category ?? null;
924
+ const prefixSlug = props.prefix ?? null;
925
925
  const defaultCategorySlug = wixStores.defaultCategory;
926
926
  let activeCategory = null;
927
927
  let baseCategoryId = null;
928
- if (subcategorySlug) {
929
- activeCategory = await findCategoryBySlug$1(wixStores.categories, subcategorySlug);
930
- baseCategoryId = activeCategory?._id ?? null;
931
- } else if (categorySlug) {
928
+ if (categorySlug) {
932
929
  activeCategory = await findCategoryBySlug$1(wixStores.categories, categorySlug);
933
930
  baseCategoryId = activeCategory?._id ?? null;
931
+ } else if (prefixSlug) {
932
+ activeCategory = await findCategoryBySlug$1(wixStores.categories, prefixSlug);
933
+ baseCategoryId = activeCategory?._id ?? null;
934
934
  } else if (defaultCategorySlug) {
935
935
  activeCategory = await findCategoryBySlug$1(wixStores.categories, defaultCategorySlug);
936
936
  }
@@ -1111,21 +1111,42 @@ async function renderFastChanging$1(props, slowCarryForward, _wixStores) {
1111
1111
  }
1112
1112
  async function* loadSearchParams([wixStores]) {
1113
1113
  try {
1114
- const result = await wixStores.categories.queryCategories({
1114
+ let findRootParent = function(cat) {
1115
+ let current = cat;
1116
+ while (current.parentCategory?._id) {
1117
+ const parent = categoryById.get(current.parentCategory._id);
1118
+ if (!parent)
1119
+ break;
1120
+ current = parent;
1121
+ }
1122
+ return current._id !== cat._id ? current : null;
1123
+ };
1124
+ const allCategories = [];
1125
+ let result = await wixStores.categories.queryCategories({
1115
1126
  treeReference: { appNamespace: "@wix/stores" }
1116
1127
  }).eq("visible", true).limit(100).find();
1117
- const categories2 = result.items || [];
1118
- yield categories2.filter((cat) => cat.slug && (cat.itemCounter ?? 0) > 0).map((cat) => ({
1119
- category: cat.slug
1120
- }));
1121
- for (const cat of categories2) {
1122
- if (!cat.slug || !cat.parentCategory?._id || (cat.itemCounter ?? 0) === 0)
1128
+ allCategories.push(...result.items || []);
1129
+ while (result.hasNext()) {
1130
+ result = await result.next();
1131
+ allCategories.push(...result.items || []);
1132
+ }
1133
+ const categoryById = /* @__PURE__ */ new Map();
1134
+ for (const cat of allCategories) {
1135
+ if (cat._id)
1136
+ categoryById.set(cat._id, cat);
1137
+ }
1138
+ const params = [];
1139
+ for (const cat of allCategories) {
1140
+ if (!cat.slug || (cat.itemCounter ?? 0) === 0)
1123
1141
  continue;
1124
- const parent = categories2.find((c) => c._id === cat.parentCategory?._id);
1125
- if (parent?.slug) {
1126
- yield [{ category: parent.slug, subcategory: cat.slug }];
1142
+ const rootParent = findRootParent(cat);
1143
+ if (rootParent?.slug) {
1144
+ params.push({ prefix: rootParent.slug, category: cat.slug });
1145
+ } else {
1146
+ params.push({ prefix: cat.slug });
1127
1147
  }
1128
1148
  }
1149
+ yield params;
1129
1150
  } catch (error) {
1130
1151
  console.error("Failed to load category params:", error);
1131
1152
  yield [];
@@ -1175,14 +1196,32 @@ var MediaType = /* @__PURE__ */ ((MediaType2) => {
1175
1196
  })(MediaType || {});
1176
1197
  async function* loadProductParams([wixStores]) {
1177
1198
  const template = wixStores.urls.product;
1178
- const needsCategories = template.includes("{category}") || template.includes("{prefix}");
1199
+ const needsPrefix = template.includes("{prefix}");
1200
+ const needsCategory = template.includes("{category}");
1201
+ const needsCategories = needsPrefix || needsCategory;
1179
1202
  const fields = needsCategories ? ["ALL_CATEGORIES_INFO"] : [];
1180
1203
  try {
1204
+ const tree = needsCategories ? await wixStores.getCategoryTree() : null;
1181
1205
  let result = await wixStores.products.queryProducts({ fields: [...fields] }).find();
1182
- yield result.items.map((product) => ({ slug: product.slug ?? "" })).filter((p) => p.slug);
1206
+ const mapProduct = (product) => {
1207
+ const slug = product.slug ?? "";
1208
+ if (!slug)
1209
+ return null;
1210
+ const params = { slug };
1211
+ if (tree && product.mainCategoryId) {
1212
+ if (needsCategory) {
1213
+ params.category = tree.slugMap.get(product.mainCategoryId);
1214
+ }
1215
+ if (needsPrefix) {
1216
+ params.prefix = findRootCategorySlug(product.mainCategoryId, tree);
1217
+ }
1218
+ }
1219
+ return params;
1220
+ };
1221
+ yield result.items.map(mapProduct).filter((p) => p !== null);
1183
1222
  while (result.hasNext()) {
1184
1223
  result = await result.next();
1185
- yield result.items.map((product) => ({ slug: product.slug ?? "" })).filter((p) => p.slug);
1224
+ yield result.items.map(mapProduct).filter((p) => p !== null);
1186
1225
  }
1187
1226
  } catch (error) {
1188
1227
  console.error("Failed to load product slugs:", error);
@@ -1227,12 +1266,19 @@ function mapMediaType(mediaType) {
1227
1266
  return MediaType.IMAGE;
1228
1267
  }
1229
1268
  function mapMedia(media) {
1230
- const mainMediaType = mapMediaType(media.main.mediaType);
1269
+ const main = media?.main;
1270
+ if (!main) {
1271
+ return {
1272
+ selectedMedia: { url: "", mediaType: MediaType.IMAGE, thumbnail_50x50: "" },
1273
+ availableMedia: []
1274
+ };
1275
+ }
1276
+ const mainMediaType = mapMediaType(main.mediaType);
1231
1277
  return {
1232
1278
  selectedMedia: {
1233
- url: formatWixMediaUrl(media.main._id, media.main.url),
1279
+ url: formatWixMediaUrl(main._id, main.url),
1234
1280
  mediaType: mainMediaType,
1235
- thumbnail_50x50: formatWixMediaUrl(media.main._id, media.main.url, { w: 50, h: 50 })
1281
+ thumbnail_50x50: formatWixMediaUrl(main._id, main.url, { w: 50, h: 50 })
1236
1282
  },
1237
1283
  availableMedia: media.itemsInfo?.items?.map((item) => ({
1238
1284
  mediaId: item._id,
@@ -1241,7 +1287,7 @@ function mapMedia(media) {
1241
1287
  mediaType: item.mediaType === "IMAGE" ? MediaType.IMAGE : MediaType.VIDEO,
1242
1288
  thumbnail_50x50: formatWixMediaUrl(item._id, item.url, { w: 50, h: 50 })
1243
1289
  },
1244
- selected: item._id === media.main._id ? Selected.selected : Selected.notSelected
1290
+ selected: item._id === main._id ? Selected.selected : Selected.notSelected
1245
1291
  })) ?? []
1246
1292
  };
1247
1293
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/wix-stores",
3
- "version": "0.15.6",
3
+ "version": "0.16.1",
4
4
  "type": "module",
5
5
  "description": "Wix Stores API client for Jay Framework",
6
6
  "license": "Apache-2.0",
@@ -35,16 +35,16 @@
35
35
  "test": ":"
36
36
  },
37
37
  "dependencies": {
38
- "@jay-framework/component": "^0.15.6",
39
- "@jay-framework/fullstack-component": "^0.15.6",
40
- "@jay-framework/reactive": "^0.15.6",
41
- "@jay-framework/runtime": "^0.15.6",
42
- "@jay-framework/secure": "^0.15.6",
43
- "@jay-framework/stack-client-runtime": "^0.15.6",
44
- "@jay-framework/stack-server-runtime": "^0.15.6",
45
- "@jay-framework/wix-cart": "^0.15.6",
46
- "@jay-framework/wix-server-client": "^0.15.6",
47
- "@jay-framework/wix-utils": "^0.15.6",
38
+ "@jay-framework/component": "^0.16.1",
39
+ "@jay-framework/fullstack-component": "^0.16.1",
40
+ "@jay-framework/reactive": "^0.16.1",
41
+ "@jay-framework/runtime": "^0.16.1",
42
+ "@jay-framework/secure": "^0.16.1",
43
+ "@jay-framework/stack-client-runtime": "^0.16.1",
44
+ "@jay-framework/stack-server-runtime": "^0.16.1",
45
+ "@jay-framework/wix-cart": "^0.16.1",
46
+ "@jay-framework/wix-server-client": "^0.16.1",
47
+ "@jay-framework/wix-utils": "^0.16.1",
48
48
  "@wix/categories": "^1.0.185",
49
49
  "@wix/sdk": "^1.21.5",
50
50
  "@wix/sdk-runtime": "^1.0.11",
@@ -55,10 +55,10 @@
55
55
  "@babel/core": "^7.23.7",
56
56
  "@babel/preset-env": "^7.23.8",
57
57
  "@babel/preset-typescript": "^7.23.3",
58
- "@jay-framework/compiler-jay-stack": "^0.15.6",
59
- "@jay-framework/jay-cli": "^0.15.6",
60
- "@jay-framework/jay-stack-cli": "^0.15.6",
61
- "@jay-framework/vite-plugin": "^0.15.6",
58
+ "@jay-framework/compiler-jay-stack": "^0.16.1",
59
+ "@jay-framework/jay-cli": "^0.16.1",
60
+ "@jay-framework/jay-stack-cli": "^0.16.1",
61
+ "@jay-framework/vite-plugin": "^0.16.1",
62
62
  "nodemon": "^3.0.3",
63
63
  "rimraf": "^5.0.5",
64
64
  "tslib": "^2.6.2",
package/plugin.yaml CHANGED
@@ -10,7 +10,7 @@ contracts:
10
10
  contract: product-search.jay-contract
11
11
  component: productSearch
12
12
  description: Headless product search page
13
- # category-page removed — use product-search with category param instead
13
+ # category-page removed — use product-search with prefix/category params instead
14
14
  - name: category-list
15
15
  contract: category-list.jay-contract
16
16
  component: categoryList