@jay-framework/wix-stores-v1 0.15.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 ADDED
@@ -0,0 +1,853 @@
1
+ import { getCurrentCartClient } from "@jay-framework/wix-cart";
2
+ import { WIX_CART_CONTEXT, WIX_CART_SERVICE, cartIndicator, cartPage, provideWixCartContext, provideWixCartService } from "@jay-framework/wix-cart";
3
+ import { inventory, collections, products } from "@wix/stores";
4
+ import { createJayService, makeJayQuery, ActionError, makeJayStackComponent, RenderPipeline, makeJayInit } from "@jay-framework/fullstack-component";
5
+ import { registerService, getService } from "@jay-framework/stack-server-runtime";
6
+ import { createJayContext } from "@jay-framework/runtime";
7
+ import "@jay-framework/component";
8
+ import { WIX_CLIENT_SERVICE } from "@jay-framework/wix-server-client";
9
+ const instances = {
10
+ productsClientInstance: void 0,
11
+ collectionsClientInstance: void 0,
12
+ inventoryClientInstance: void 0
13
+ };
14
+ function getProductsClient(wixClient) {
15
+ if (!instances.productsClientInstance) {
16
+ instances.productsClientInstance = wixClient.use(products);
17
+ }
18
+ return instances.productsClientInstance;
19
+ }
20
+ function getCollectionsClient(wixClient) {
21
+ if (!instances.collectionsClientInstance) {
22
+ instances.collectionsClientInstance = wixClient.use(collections);
23
+ }
24
+ return instances.collectionsClientInstance;
25
+ }
26
+ function getInventoryClient(wixClient) {
27
+ if (!instances.inventoryClientInstance) {
28
+ instances.inventoryClientInstance = wixClient.use(inventory);
29
+ }
30
+ return instances.inventoryClientInstance;
31
+ }
32
+ const WIX_STORES_V1_SERVICE_MARKER = createJayService("Wix Store V1 Service");
33
+ function provideWixStoresV1Service(wixClient) {
34
+ const service = {
35
+ products: getProductsClient(wixClient),
36
+ collections: getCollectionsClient(wixClient),
37
+ inventory: getInventoryClient(wixClient),
38
+ // Keep cart for backward compatibility, but prefer WIX_CART_SERVICE
39
+ cart: getCurrentCartClient(wixClient)
40
+ };
41
+ registerService(WIX_STORES_V1_SERVICE_MARKER, service);
42
+ return service;
43
+ }
44
+ var MediaType$2 = /* @__PURE__ */ ((MediaType2) => {
45
+ MediaType2[MediaType2["IMAGE"] = 0] = "IMAGE";
46
+ MediaType2[MediaType2["VIDEO"] = 1] = "VIDEO";
47
+ return MediaType2;
48
+ })(MediaType$2 || {});
49
+ var AvailabilityStatus = /* @__PURE__ */ ((AvailabilityStatus2) => {
50
+ AvailabilityStatus2[AvailabilityStatus2["IN_STOCK"] = 0] = "IN_STOCK";
51
+ AvailabilityStatus2[AvailabilityStatus2["OUT_OF_STOCK"] = 1] = "OUT_OF_STOCK";
52
+ AvailabilityStatus2[AvailabilityStatus2["PARTIALLY_OUT_OF_STOCK"] = 2] = "PARTIALLY_OUT_OF_STOCK";
53
+ return AvailabilityStatus2;
54
+ })(AvailabilityStatus || {});
55
+ var PreorderStatus = /* @__PURE__ */ ((PreorderStatus2) => {
56
+ PreorderStatus2[PreorderStatus2["ENABLED"] = 0] = "ENABLED";
57
+ PreorderStatus2[PreorderStatus2["DISABLED"] = 1] = "DISABLED";
58
+ PreorderStatus2[PreorderStatus2["PARTIALLY_ENABLED"] = 2] = "PARTIALLY_ENABLED";
59
+ return PreorderStatus2;
60
+ })(PreorderStatus || {});
61
+ var ProductType$1 = /* @__PURE__ */ ((ProductType2) => {
62
+ ProductType2[ProductType2["PHYSICAL"] = 0] = "PHYSICAL";
63
+ ProductType2[ProductType2["DIGITAL"] = 1] = "DIGITAL";
64
+ return ProductType2;
65
+ })(ProductType$1 || {});
66
+ var QuickAddType = /* @__PURE__ */ ((QuickAddType2) => {
67
+ QuickAddType2[QuickAddType2["SIMPLE"] = 0] = "SIMPLE";
68
+ QuickAddType2[QuickAddType2["SINGLE_OPTION"] = 1] = "SINGLE_OPTION";
69
+ QuickAddType2[QuickAddType2["NEEDS_CONFIGURATION"] = 2] = "NEEDS_CONFIGURATION";
70
+ return QuickAddType2;
71
+ })(QuickAddType || {});
72
+ var OptionRenderType$1 = /* @__PURE__ */ ((OptionRenderType2) => {
73
+ OptionRenderType2[OptionRenderType2["TEXT_CHOICES"] = 0] = "TEXT_CHOICES";
74
+ OptionRenderType2[OptionRenderType2["COLOR_SWATCH_CHOICES"] = 1] = "COLOR_SWATCH_CHOICES";
75
+ return OptionRenderType2;
76
+ })(OptionRenderType$1 || {});
77
+ var ChoiceType$1 = /* @__PURE__ */ ((ChoiceType2) => {
78
+ ChoiceType2[ChoiceType2["CHOICE_TEXT"] = 0] = "CHOICE_TEXT";
79
+ ChoiceType2[ChoiceType2["ONE_COLOR"] = 1] = "ONE_COLOR";
80
+ return ChoiceType2;
81
+ })(ChoiceType$1 || {});
82
+ function mapAvailabilityStatus(status) {
83
+ switch (status) {
84
+ case "OUT_OF_STOCK":
85
+ return AvailabilityStatus.OUT_OF_STOCK;
86
+ case "PARTIALLY_OUT_OF_STOCK":
87
+ return AvailabilityStatus.PARTIALLY_OUT_OF_STOCK;
88
+ default:
89
+ return AvailabilityStatus.IN_STOCK;
90
+ }
91
+ }
92
+ function mapPreorderStatus() {
93
+ return PreorderStatus.DISABLED;
94
+ }
95
+ function mapMediaType(mediaType) {
96
+ return mediaType === "video" ? MediaType$2.VIDEO : MediaType$2.IMAGE;
97
+ }
98
+ function mapProductType$1(productType) {
99
+ return productType === "digital" ? ProductType$1.DIGITAL : ProductType$1.PHYSICAL;
100
+ }
101
+ function hasProductDiscount(product) {
102
+ const price = product.price?.price || 0;
103
+ const discountedPrice = product.price?.discountedPrice || price;
104
+ return discountedPrice < price;
105
+ }
106
+ function getQuickAddType(product) {
107
+ const optionCount = product.productOptions?.length ?? 0;
108
+ if (optionCount > 1) {
109
+ return QuickAddType.NEEDS_CONFIGURATION;
110
+ }
111
+ if (optionCount === 1) {
112
+ return QuickAddType.SINGLE_OPTION;
113
+ }
114
+ return QuickAddType.SIMPLE;
115
+ }
116
+ function mapOptionRenderType(optionType) {
117
+ return optionType === "color" ? OptionRenderType$1.COLOR_SWATCH_CHOICES : OptionRenderType$1.TEXT_CHOICES;
118
+ }
119
+ function mapQuickOption(option, variants) {
120
+ if (!option) return null;
121
+ const choices = option.choices || [];
122
+ return {
123
+ _id: option.name,
124
+ name: option.name || "",
125
+ optionRenderType: mapOptionRenderType(option.optionType),
126
+ choices: choices.map((choice) => {
127
+ const variant = variants?.find((v) => Object.values(v.choices).includes(choice.value));
128
+ return {
129
+ choiceId: choice.description,
130
+ name: choice.value || "",
131
+ choiceType: option.optionType === "color" ? ChoiceType$1.ONE_COLOR : ChoiceType$1.CHOICE_TEXT,
132
+ colorCode: "",
133
+ // V1 doesn't store color code in choices
134
+ inStock: variant?.stock?.inStock ?? choice.inStock ?? true,
135
+ variantId: variant?._id || "",
136
+ isSelected: false
137
+ };
138
+ })
139
+ };
140
+ }
141
+ const DEFAULT_PRODUCT_PAGE_PATH = "/products";
142
+ function mapProductToCard(product, productPagePath = DEFAULT_PRODUCT_PAGE_PATH) {
143
+ const mainMedia = product.media?.mainMedia;
144
+ const slug = product.slug || "";
145
+ product.price?.discountedPrice ?? product.price?.price ?? 0;
146
+ product.price?.price ?? 0;
147
+ const formattedActualPrice = product.price?.formatted?.discountedPrice || "";
148
+ const formattedCompareAtPrice = product.price?.formatted?.price || "";
149
+ const hasDiscount = hasProductDiscount(product);
150
+ console.log("product", product.name, product.slug);
151
+ return {
152
+ _id: product._id || "",
153
+ name: product.name || "",
154
+ slug,
155
+ productUrl: slug ? `${productPagePath}/${slug}` : "",
156
+ mainMedia: {
157
+ // V1 provides complete URLs
158
+ url: mainMedia?.image?.url || "",
159
+ altText: mainMedia?.title || product.name || "",
160
+ mediaType: mapMediaType(mainMedia?.mediaType)
161
+ },
162
+ thumbnail: {
163
+ // V1 provides complete thumbnail URLs
164
+ url: mainMedia?.thumbnail?.url || "",
165
+ altText: mainMedia?.title || product.name || "",
166
+ width: mainMedia?.thumbnail?.width || 300,
167
+ height: mainMedia?.thumbnail?.height || 300
168
+ },
169
+ // Simplified price fields
170
+ price: formattedActualPrice,
171
+ strikethroughPrice: hasDiscount ? formattedCompareAtPrice : "",
172
+ hasDiscount,
173
+ inventory: {
174
+ // V1 uses stock.inventoryStatus
175
+ availabilityStatus: mapAvailabilityStatus(product.stock?.inventoryStatus),
176
+ preorderStatus: mapPreorderStatus()
177
+ },
178
+ ribbon: {
179
+ _id: product.ribbon || "",
180
+ name: product.ribbon || ""
181
+ },
182
+ hasRibbon: !!product.ribbon,
183
+ brand: {
184
+ _id: product.brand || "",
185
+ name: product.brand || ""
186
+ },
187
+ productType: mapProductType$1(product.productType),
188
+ isAddingToCart: false,
189
+ // Quick add behavior
190
+ quickAddType: getQuickAddType(product),
191
+ quickOption: getQuickAddType(product) === QuickAddType.SINGLE_OPTION ? mapQuickOption(product.productOptions?.[0], product.variants) : null
192
+ };
193
+ }
194
+ function mapCollectionToViewState(collection) {
195
+ return {
196
+ _id: collection._id,
197
+ name: collection.name || "",
198
+ slug: collection.slug || "",
199
+ description: collection.description || "",
200
+ imageUrl: collection.media?.mainMedia?.image?.url || "",
201
+ productCount: collection.numberOfProducts || 0
202
+ };
203
+ }
204
+ const WIX_STORES_V1_CONTEXT = createJayContext();
205
+ function getNiceBoundaries(minPrice, maxPrice) {
206
+ const multipliers = [1, 2, 5];
207
+ const boundaries = [];
208
+ let magnitude = 1;
209
+ while (magnitude <= maxPrice * 10) {
210
+ for (const mult of multipliers) {
211
+ const value = magnitude * mult;
212
+ if (value > minPrice && value < maxPrice) {
213
+ boundaries.push(value);
214
+ }
215
+ }
216
+ magnitude *= 10;
217
+ }
218
+ return boundaries.sort((a, b) => a - b);
219
+ }
220
+ function generatePriceBuckets(minPrice, maxPrice, currencySymbol = "$") {
221
+ if (maxPrice <= minPrice || maxPrice === 0) {
222
+ return [
223
+ { rangeId: "all", label: "Show all", minValue: null, maxValue: null, isSelected: true }
224
+ ];
225
+ }
226
+ let niceBoundaries = getNiceBoundaries(minPrice, maxPrice);
227
+ while (niceBoundaries.length > 5) {
228
+ niceBoundaries = niceBoundaries.filter((_, i) => i % 2 === 0);
229
+ }
230
+ const allBoundaries = [minPrice, ...niceBoundaries, maxPrice];
231
+ const buckets = [
232
+ { rangeId: "all", label: "Show all", minValue: null, maxValue: null, isSelected: true }
233
+ ];
234
+ for (let i = 0; i < allBoundaries.length - 1; i++) {
235
+ const from = Math.round(allBoundaries[i]);
236
+ const to = Math.round(allBoundaries[i + 1]);
237
+ if (from < to) {
238
+ const label = `${currencySymbol}${from} - ${currencySymbol}${to}`;
239
+ buckets.push({
240
+ rangeId: `${from}-${to}`,
241
+ label,
242
+ minValue: from,
243
+ maxValue: to,
244
+ isSelected: false
245
+ });
246
+ }
247
+ }
248
+ return buckets;
249
+ }
250
+ const searchProducts = makeJayQuery("wixStoresV1.searchProducts").withServices(WIX_STORES_V1_SERVICE_MARKER).withHandler(
251
+ async (input, wixStores) => {
252
+ const { query, filters = {}, sortBy = "relevance", page = 1, pageSize = 12 } = input;
253
+ try {
254
+ const buildBaseQuery = () => {
255
+ let q = wixStores.products.queryProducts();
256
+ if (query && query.trim().length > 0) {
257
+ q = q.startsWith("name", query.trim());
258
+ }
259
+ if (filters.collectionIds && filters.collectionIds.length > 0) {
260
+ q = q.hasSome("collectionIds", filters.collectionIds);
261
+ }
262
+ return q;
263
+ };
264
+ const buildProductsQuery = () => {
265
+ let q = buildBaseQuery().limit(pageSize).skip((page - 1) * pageSize);
266
+ if (filters.minPrice !== void 0 && filters.minPrice > 0) {
267
+ q = q.ge("priceData.price", filters.minPrice);
268
+ }
269
+ if (filters.maxPrice !== void 0 && filters.maxPrice > 0) {
270
+ q = q.le("priceData.price", filters.maxPrice);
271
+ }
272
+ switch (sortBy) {
273
+ case "price_asc":
274
+ q = q.ascending("price");
275
+ break;
276
+ case "price_desc":
277
+ q = q.descending("price");
278
+ break;
279
+ case "name_asc":
280
+ q = q.ascending("name");
281
+ break;
282
+ case "name_desc":
283
+ q = q.descending("name");
284
+ break;
285
+ case "newest":
286
+ q = q.descending("lastUpdated");
287
+ break;
288
+ }
289
+ return q;
290
+ };
291
+ const minPriceQuery = buildBaseQuery().ascending("price").limit(1).find();
292
+ const maxPriceQuery = buildBaseQuery().descending("price").limit(1).find();
293
+ const [result, minPriceResult, maxPriceResult] = await Promise.all([
294
+ buildProductsQuery().find(),
295
+ minPriceQuery,
296
+ maxPriceQuery
297
+ ]);
298
+ const products2 = result.items || [];
299
+ const minBound = minPriceResult.items?.[0]?.price?.price ?? minPriceResult.items?.[0]?.priceData?.price ?? 0;
300
+ const maxBound = maxPriceResult.items?.[0]?.price?.price ?? maxPriceResult.items?.[0]?.priceData?.price ?? 0;
301
+ const currency = products2[0]?.price?.currency || products2[0]?.priceData?.currency || minPriceResult.items?.[0]?.price?.currency;
302
+ const currencySymbol = currency === "ILS" ? "₪" : currency === "USD" ? "$" : currency === "EUR" ? "€" : currency === "GBP" ? "£" : "$";
303
+ const ranges = generatePriceBuckets(minBound, maxBound, currencySymbol);
304
+ const totalCount = result.totalCount ?? result.items?.length ?? 0;
305
+ const totalPages = Math.ceil(totalCount / pageSize);
306
+ const mappedProducts = products2.map((p) => mapProductToCard(p));
307
+ return {
308
+ products: mappedProducts,
309
+ totalCount,
310
+ currentPage: page,
311
+ totalPages,
312
+ hasMore: page < totalPages,
313
+ priceAggregation: { minBound, maxBound, ranges }
314
+ };
315
+ } catch (error) {
316
+ console.error("[wixStoresV1.searchProducts] Search failed:", error);
317
+ throw new ActionError("SEARCH_FAILED", "Failed to search products");
318
+ }
319
+ }
320
+ );
321
+ const getProductBySlug = makeJayQuery("wixStoresV1.getProductBySlug").withServices(WIX_STORES_V1_SERVICE_MARKER).withCaching({ maxAge: 300, staleWhileRevalidate: 600 }).withHandler(
322
+ async (input, wixStores) => {
323
+ const { slug } = input;
324
+ if (!slug) {
325
+ throw new ActionError("INVALID_INPUT", "Product slug is required");
326
+ }
327
+ try {
328
+ let result = await wixStores.products.queryProducts().eq("slug", slug).limit(1).find();
329
+ if (!result.items?.length) {
330
+ result = await wixStores.products.queryProducts().eq("_id", slug).limit(1).find();
331
+ }
332
+ const product = result.items?.[0];
333
+ if (!product) {
334
+ return null;
335
+ }
336
+ return mapProductToCard(product);
337
+ } catch (error) {
338
+ console.error("[wixStoresV1.getProductBySlug] Failed to get product:", error);
339
+ return null;
340
+ }
341
+ }
342
+ );
343
+ const getCollections = makeJayQuery("wixStoresV1.getCollections").withServices(WIX_STORES_V1_SERVICE_MARKER).withCaching({ maxAge: 3600 }).withHandler(
344
+ async (_input, wixStores) => {
345
+ try {
346
+ const result = await wixStores.collections.queryCollections().find();
347
+ return (result.items || []).map((col) => mapCollectionToViewState(col));
348
+ } catch (error) {
349
+ console.error("[wixStoresV1.getCollections] Failed to load collections:", error);
350
+ throw new ActionError("LOAD_FAILED", "Failed to load collections");
351
+ }
352
+ }
353
+ );
354
+ var ProductType = /* @__PURE__ */ ((ProductType2) => {
355
+ ProductType2[ProductType2["PHYSICAL"] = 0] = "PHYSICAL";
356
+ ProductType2[ProductType2["DIGITAL"] = 1] = "DIGITAL";
357
+ return ProductType2;
358
+ })(ProductType || {});
359
+ var StockStatus = /* @__PURE__ */ ((StockStatus2) => {
360
+ StockStatus2[StockStatus2["OUT_OF_STOCK"] = 0] = "OUT_OF_STOCK";
361
+ StockStatus2[StockStatus2["IN_STOCK"] = 1] = "IN_STOCK";
362
+ return StockStatus2;
363
+ })(StockStatus || {});
364
+ var OptionRenderType = /* @__PURE__ */ ((OptionRenderType2) => {
365
+ OptionRenderType2[OptionRenderType2["TEXT_CHOICES"] = 0] = "TEXT_CHOICES";
366
+ OptionRenderType2[OptionRenderType2["COLOR_SWATCH_CHOICES"] = 1] = "COLOR_SWATCH_CHOICES";
367
+ return OptionRenderType2;
368
+ })(OptionRenderType || {});
369
+ var ChoiceType = /* @__PURE__ */ ((ChoiceType2) => {
370
+ ChoiceType2[ChoiceType2["CHOICE_TEXT"] = 0] = "CHOICE_TEXT";
371
+ ChoiceType2[ChoiceType2["ONE_COLOR"] = 1] = "ONE_COLOR";
372
+ return ChoiceType2;
373
+ })(ChoiceType || {});
374
+ var ChoiceType = /* @__PURE__ */ ((ChoiceType2) => {
375
+ ChoiceType2[ChoiceType2["CHOICE_TEXT"] = 0] = "CHOICE_TEXT";
376
+ ChoiceType2[ChoiceType2["ONE_COLOR"] = 1] = "ONE_COLOR";
377
+ return ChoiceType2;
378
+ })(ChoiceType || {});
379
+ var Selected = /* @__PURE__ */ ((Selected2) => {
380
+ Selected2[Selected2["selected"] = 0] = "selected";
381
+ Selected2[Selected2["notSelected"] = 1] = "notSelected";
382
+ return Selected2;
383
+ })(Selected || {});
384
+ var MediaType$1 = /* @__PURE__ */ ((MediaType2) => {
385
+ MediaType2[MediaType2["IMAGE"] = 0] = "IMAGE";
386
+ MediaType2[MediaType2["VIDEO"] = 1] = "VIDEO";
387
+ return MediaType2;
388
+ })(MediaType$1 || {});
389
+ function mapProductType(productType) {
390
+ return productType === "digital" ? ProductType.DIGITAL : ProductType.PHYSICAL;
391
+ }
392
+ function mapInfoSections(sections) {
393
+ return (sections || []).map((section, index) => ({
394
+ _id: String(index),
395
+ title: section.title || "",
396
+ plainDescription: section.description || "",
397
+ uniqueName: section.title || ""
398
+ }));
399
+ }
400
+ function mapMedia(product) {
401
+ const mainMedia = product.media?.mainMedia;
402
+ const mediaItems = product.media?.items || [];
403
+ const mainUrl = mainMedia?.image?.url || "";
404
+ const mainThumbnail = mainMedia?.thumbnail?.url || "";
405
+ const mainMediaType = mainMedia?.mediaType === "video" ? MediaType$1.VIDEO : MediaType$1.IMAGE;
406
+ return {
407
+ selectedMedia: {
408
+ url: mainUrl,
409
+ mediaType: mainMediaType,
410
+ thumbnail_50x50: mainThumbnail
411
+ },
412
+ availableMedia: mediaItems.map((item, index) => ({
413
+ mediaId: item._id || String(index),
414
+ media: {
415
+ url: item.image?.url || "",
416
+ mediaType: item.mediaType === "video" ? MediaType$1.VIDEO : MediaType$1.IMAGE,
417
+ thumbnail_50x50: item.thumbnail?.url || ""
418
+ },
419
+ selected: item._id === mainMedia?._id ? Selected.selected : Selected.notSelected
420
+ }))
421
+ };
422
+ }
423
+ function mapOptionsToSlowVS(product) {
424
+ return (product.productOptions || []).map((option) => ({
425
+ _id: option.name || "",
426
+ name: option.name || "",
427
+ optionRenderType: option.optionType === "color" ? OptionRenderType.COLOR_SWATCH_CHOICES : OptionRenderType.TEXT_CHOICES,
428
+ choices: (option.choices || []).map((choice) => ({
429
+ choiceId: choice.value || "",
430
+ name: choice.value || "",
431
+ choiceType: option.optionType === "color" ? ChoiceType.ONE_COLOR : ChoiceType.CHOICE_TEXT,
432
+ inStock: choice.inStock ?? true,
433
+ colorCode: ""
434
+ }))
435
+ }));
436
+ }
437
+ function mapOptionsToFastVS(product) {
438
+ return (product.productOptions || []).map((option) => ({
439
+ _id: option.name || "",
440
+ textChoiceSelection: void 0,
441
+ choices: (option.choices || []).map((choice) => ({
442
+ choiceId: choice.value || "",
443
+ isSelected: false
444
+ }))
445
+ }));
446
+ }
447
+ function mapVariants(product) {
448
+ return (product.variants || []).map((variant) => ({
449
+ _id: variant._id || "",
450
+ sku: variant.variant?.sku || "",
451
+ price: variant.variant?.priceData?.formatted?.discountedPrice || variant.variant?.priceData?.formatted?.price || "",
452
+ strikethroughPrice: variant.variant?.priceData?.discountedPrice < variant.variant?.priceData?.price ? variant.variant?.priceData?.formatted?.price || "" : "",
453
+ choices: variant.choices || {},
454
+ inventoryStatus: variant.stock?.inStock ? StockStatus.IN_STOCK : StockStatus.OUT_OF_STOCK
455
+ }));
456
+ }
457
+ async function* loadProductParams([wixStores]) {
458
+ try {
459
+ let result = await wixStores.products.queryProducts().find();
460
+ yield result.items.map((product) => ({ slug: product.slug || "" }));
461
+ while (result.hasNext()) {
462
+ result = await result.next();
463
+ yield result.items.map((product) => ({ slug: product.slug || "" }));
464
+ }
465
+ } catch (error) {
466
+ console.error("[ProductPage V1] Failed to load product slugs:", error);
467
+ yield [];
468
+ }
469
+ }
470
+ async function renderSlowlyChanging$3(props, wixStores) {
471
+ const Pipeline = RenderPipeline.for();
472
+ return Pipeline.try(async () => {
473
+ const bySlug = await wixStores.products.queryProducts().eq("slug", props.slug).limit(1).find();
474
+ if (bySlug.items?.length)
475
+ return bySlug;
476
+ return wixStores.products.queryProducts().eq("_id", props.slug).limit(1).find();
477
+ }).recover((error) => {
478
+ console.error("[ProductPage V1] Error loading product:", error);
479
+ return Pipeline.clientError(404, "Product not found");
480
+ }).toPhaseOutput((result) => {
481
+ const product = result.items?.[0];
482
+ if (!product) {
483
+ throw new Error("Product not found");
484
+ }
485
+ const variants = mapVariants(product);
486
+ const stockStatus = product.stock?.inStock ? StockStatus.IN_STOCK : StockStatus.OUT_OF_STOCK;
487
+ return {
488
+ viewState: {
489
+ _id: product._id || "",
490
+ productName: product.name || "",
491
+ description: product.description || "",
492
+ brand: product.brand || "",
493
+ ribbon: product.ribbon || "",
494
+ productType: mapProductType(product.productType),
495
+ options: mapOptionsToSlowVS(product),
496
+ infoSections: mapInfoSections(product.additionalInfoSections),
497
+ modifiers: [],
498
+ // V1 doesn't have modifiers in same format
499
+ seoData: { tags: [], settings: { preventAutoRedirect: false, keywords: [] } }
500
+ },
501
+ carryForward: {
502
+ productId: product._id || "",
503
+ mediaGallery: mapMedia(product),
504
+ options: mapOptionsToFastVS(product),
505
+ pricePerUnit: "",
506
+ stockStatus,
507
+ variants
508
+ }
509
+ };
510
+ });
511
+ }
512
+ async function renderFastChanging$2(props, slowCarryForward, wixStores) {
513
+ const Pipeline = RenderPipeline.for();
514
+ const isInStock = slowCarryForward.stockStatus === StockStatus.IN_STOCK;
515
+ const firstVariant = slowCarryForward.variants[0];
516
+ return Pipeline.ok({
517
+ actionsEnabled: isInStock,
518
+ options: slowCarryForward.options,
519
+ modifiers: [],
520
+ mediaGallery: slowCarryForward.mediaGallery,
521
+ sku: firstVariant?.sku || "",
522
+ price: firstVariant?.price || "",
523
+ pricePerUnit: slowCarryForward.pricePerUnit,
524
+ stockStatus: slowCarryForward.stockStatus,
525
+ strikethroughPrice: firstVariant?.strikethroughPrice || "",
526
+ quantity: { quantity: 1 }
527
+ }).toPhaseOutput((viewState) => ({
528
+ viewState,
529
+ carryForward: {
530
+ productId: slowCarryForward.productId,
531
+ variants: slowCarryForward.variants
532
+ }
533
+ }));
534
+ }
535
+ const productPage = makeJayStackComponent().withProps().withServices(WIX_STORES_V1_SERVICE_MARKER).withLoadParams(loadProductParams).withSlowlyRender(renderSlowlyChanging$3).withFastRender(renderFastChanging$2);
536
+ var CurrentSort = /* @__PURE__ */ ((CurrentSort2) => {
537
+ CurrentSort2[CurrentSort2["relevance"] = 0] = "relevance";
538
+ CurrentSort2[CurrentSort2["priceAsc"] = 1] = "priceAsc";
539
+ CurrentSort2[CurrentSort2["priceDesc"] = 2] = "priceDesc";
540
+ CurrentSort2[CurrentSort2["newest"] = 3] = "newest";
541
+ CurrentSort2[CurrentSort2["nameAsc"] = 4] = "nameAsc";
542
+ CurrentSort2[CurrentSort2["nameDesc"] = 5] = "nameDesc";
543
+ return CurrentSort2;
544
+ })(CurrentSort || {});
545
+ const PAGE_SIZE$1 = 12;
546
+ async function renderSlowlyChanging$2(props, wixStores) {
547
+ const Pipeline = RenderPipeline.for();
548
+ return Pipeline.try(async () => {
549
+ const collectionsResult = await wixStores.collections.queryCollections().find();
550
+ return collectionsResult.items || [];
551
+ }).recover((error) => {
552
+ console.error("[ProductSearch V1] Failed to load collections:", error);
553
+ return Pipeline.ok([]);
554
+ }).toPhaseOutput((collections2) => {
555
+ const collectionInfos = collections2.map((col) => ({
556
+ categoryId: col._id || "",
557
+ categoryName: col.name || "",
558
+ categorySlug: col.slug || ""
559
+ }));
560
+ return {
561
+ viewState: {
562
+ searchFields: "name,description,sku",
563
+ fuzzySearch: false,
564
+ // V1 doesn't support fuzzy search
565
+ emptyStateMessage: "Enter a search term to find products",
566
+ filters: {
567
+ categoryFilter: {
568
+ categories: collectionInfos
569
+ }
570
+ }
571
+ },
572
+ carryForward: {
573
+ searchFields: "name,description,sku",
574
+ fuzzySearch: false,
575
+ collections: collectionInfos
576
+ }
577
+ };
578
+ });
579
+ }
580
+ async function renderFastChanging$1(props, slowCarryForward, _wixStores) {
581
+ const Pipeline = RenderPipeline.for();
582
+ return Pipeline.try(async () => {
583
+ const result = await searchProducts({
584
+ query: "",
585
+ pageSize: PAGE_SIZE$1,
586
+ page: 1
587
+ });
588
+ return result;
589
+ }).recover((error) => {
590
+ console.error("[ProductSearch V1] Failed to load products:", error);
591
+ return Pipeline.ok({
592
+ products: [],
593
+ totalCount: 0,
594
+ currentPage: 1,
595
+ totalPages: 0,
596
+ hasMore: false,
597
+ priceAggregation: {
598
+ minBound: 0,
599
+ maxBound: 1e4,
600
+ ranges: [
601
+ {
602
+ rangeId: "all",
603
+ label: "Show all",
604
+ minValue: null,
605
+ maxValue: null,
606
+ productCount: 0,
607
+ isSelected: true
608
+ }
609
+ ]
610
+ }
611
+ });
612
+ }).toPhaseOutput((result) => {
613
+ return {
614
+ viewState: {
615
+ searchExpression: "",
616
+ isSearching: false,
617
+ hasSearched: false,
618
+ searchResults: result.products,
619
+ resultCount: result.products.length,
620
+ hasResults: result.products.length > 0,
621
+ hasSuggestions: false,
622
+ suggestions: [],
623
+ filters: {
624
+ priceRange: {
625
+ minPrice: 0,
626
+ maxPrice: 0,
627
+ minBound: result.priceAggregation?.minBound ?? 0,
628
+ maxBound: result.priceAggregation?.maxBound ?? 1e4,
629
+ ranges: result.priceAggregation?.ranges ?? [
630
+ {
631
+ rangeId: "all",
632
+ label: "Show all",
633
+ minValue: null,
634
+ maxValue: null,
635
+ isSelected: true
636
+ }
637
+ ]
638
+ },
639
+ categoryFilter: {
640
+ categories: slowCarryForward.collections.map((col) => ({
641
+ categoryId: col.categoryId,
642
+ isSelected: false
643
+ }))
644
+ }
645
+ },
646
+ sortBy: {
647
+ currentSort: CurrentSort.relevance
648
+ },
649
+ hasMore: result.hasMore,
650
+ loadedCount: result.products.length,
651
+ totalCount: result.totalCount
652
+ },
653
+ carryForward: {
654
+ searchFields: slowCarryForward.searchFields,
655
+ fuzzySearch: slowCarryForward.fuzzySearch,
656
+ collections: slowCarryForward.collections
657
+ }
658
+ };
659
+ });
660
+ }
661
+ const productSearch = makeJayStackComponent().withProps().withServices(WIX_STORES_V1_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$2).withFastRender(renderFastChanging$1);
662
+ async function renderSlowlyChanging$1(props, wixStores) {
663
+ const Pipeline = RenderPipeline.for();
664
+ return Pipeline.try(async () => {
665
+ const result = await wixStores.collections.queryCollections().find();
666
+ return result.items || [];
667
+ }).recover((error) => {
668
+ console.error("[CollectionList V1] Failed to load collections:", error);
669
+ return Pipeline.ok([]);
670
+ }).toPhaseOutput((collections2) => {
671
+ const collectionItems = collections2.map((col) => {
672
+ const imageUrl = col.media?.mainMedia?.image?.url || "";
673
+ return {
674
+ _id: col._id || "",
675
+ name: col.name || "",
676
+ slug: col.slug || "",
677
+ description: col.description || "",
678
+ productCount: col.numberOfProducts || 0,
679
+ imageUrl,
680
+ hasImage: !!imageUrl
681
+ };
682
+ });
683
+ return {
684
+ viewState: {
685
+ // Reuse 'categories' field from contract for compatibility
686
+ categories: collectionItems,
687
+ hasCategories: collectionItems.length > 0
688
+ },
689
+ carryForward: {}
690
+ };
691
+ });
692
+ }
693
+ const collectionList = makeJayStackComponent().withProps().withServices(WIX_STORES_V1_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$1);
694
+ const categoryList = collectionList;
695
+ var MediaType = /* @__PURE__ */ ((MediaType2) => {
696
+ MediaType2[MediaType2["IMAGE"] = 0] = "IMAGE";
697
+ MediaType2[MediaType2["VIDEO"] = 1] = "VIDEO";
698
+ MediaType2[MediaType2["AUDIO"] = 2] = "AUDIO";
699
+ MediaType2[MediaType2["DOCUMENT"] = 3] = "DOCUMENT";
700
+ MediaType2[MediaType2["ZIP"] = 4] = "ZIP";
701
+ return MediaType2;
702
+ })(MediaType || {});
703
+ var MediaType = /* @__PURE__ */ ((MediaType2) => {
704
+ MediaType2[MediaType2["IMAGE"] = 0] = "IMAGE";
705
+ MediaType2[MediaType2["VIDEO"] = 1] = "VIDEO";
706
+ MediaType2[MediaType2["AUDIO"] = 2] = "AUDIO";
707
+ MediaType2[MediaType2["DOCUMENT"] = 3] = "DOCUMENT";
708
+ MediaType2[MediaType2["ZIP"] = 4] = "ZIP";
709
+ return MediaType2;
710
+ })(MediaType || {});
711
+ const PAGE_SIZE = 20;
712
+ async function* loadCollectionParams([wixStores]) {
713
+ try {
714
+ const result = await wixStores.collections.queryCollections().find();
715
+ yield (result.items || []).filter((col) => col.slug).map((col) => ({ slug: col.slug }));
716
+ } catch (error) {
717
+ console.error("[CollectionPage V1] Failed to load collection slugs:", error);
718
+ yield [];
719
+ }
720
+ }
721
+ async function loadCollectionProducts(collectionId, wixStores, offset = 0) {
722
+ const result = await wixStores.products.queryProducts().hasSome("collectionIds", [collectionId]).skip(offset).limit(PAGE_SIZE).find();
723
+ const products2 = (result.items || []).map((product) => mapProductToCard(product, "/products"));
724
+ return {
725
+ products: products2,
726
+ total: result.totalCount || products2.length
727
+ };
728
+ }
729
+ function mapCollectionMedia(collection) {
730
+ const mainMedia = collection.media?.mainMedia;
731
+ return {
732
+ mainMedia: mainMedia?.image?.url ? {
733
+ _id: "",
734
+ url: mainMedia.image.url,
735
+ altText: collection.name || "",
736
+ mediaType: MediaType.IMAGE
737
+ } : void 0,
738
+ items: []
739
+ };
740
+ }
741
+ async function renderSlowlyChanging(props, wixStores) {
742
+ const Pipeline = RenderPipeline.for();
743
+ return Pipeline.try(async () => {
744
+ const result = await wixStores.collections.queryCollections().find();
745
+ const collection = (result.items || []).find((col) => col.slug === props.slug);
746
+ if (!collection) {
747
+ throw new Error("Collection not found");
748
+ }
749
+ const productData = await loadCollectionProducts(collection._id, wixStores, 0);
750
+ return { collection, productData };
751
+ }).recover((error) => {
752
+ console.error("[CollectionPage V1] Failed to load collection:", error);
753
+ return Pipeline.clientError(404, "Collection not found");
754
+ }).toPhaseOutput((data) => {
755
+ const { collection, productData } = data;
756
+ const breadcrumbs = [
757
+ {
758
+ categoryId: collection._id || "",
759
+ categoryName: collection.name || "",
760
+ categorySlug: collection.slug || ""
761
+ }
762
+ ];
763
+ const media = mapCollectionMedia(collection);
764
+ return {
765
+ viewState: {
766
+ _id: collection._id || "",
767
+ name: collection.name || "",
768
+ description: collection.description || "",
769
+ slug: collection.slug || "",
770
+ visible: true,
771
+ numberOfProducts: collection.numberOfProducts || productData.total,
772
+ hasImage: !!media.mainMedia?.url,
773
+ media,
774
+ breadcrumbs,
775
+ products: productData.products
776
+ },
777
+ carryForward: {
778
+ collectionId: collection._id || "",
779
+ collectionSlug: collection.slug || "",
780
+ totalProducts: productData.total,
781
+ products: productData.products,
782
+ currentOffset: productData.products.length
783
+ }
784
+ };
785
+ });
786
+ }
787
+ async function renderFastChanging(props, slowCarryForward, _wixStores) {
788
+ const Pipeline = RenderPipeline.for();
789
+ const hasMore = slowCarryForward.currentOffset < slowCarryForward.totalProducts;
790
+ return Pipeline.ok(slowCarryForward).toPhaseOutput((data) => {
791
+ return {
792
+ viewState: {
793
+ // Products array with fast+interactive properties for SSR items
794
+ products: data.products.map((p) => ({
795
+ _id: p._id,
796
+ price: p.price,
797
+ strikethroughPrice: p.strikethroughPrice,
798
+ isAddingToCart: false,
799
+ quickOption: p.quickOption ? {
800
+ choices: p.quickOption.choices.map((c) => ({
801
+ choiceId: c.choiceId,
802
+ inStock: c.inStock,
803
+ isSelected: c.isSelected
804
+ }))
805
+ } : { choices: [] }
806
+ })),
807
+ loadedProducts: [],
808
+ hasMore,
809
+ loadedCount: data.products.length,
810
+ isLoading: false,
811
+ hasProducts: data.products.length > 0
812
+ },
813
+ carryForward: {
814
+ collectionId: data.collectionId,
815
+ totalProducts: data.totalProducts,
816
+ currentOffset: data.currentOffset
817
+ }
818
+ };
819
+ });
820
+ }
821
+ const collectionPage = makeJayStackComponent().withProps().withServices(WIX_STORES_V1_SERVICE_MARKER).withLoadParams(loadCollectionParams).withSlowlyRender(renderSlowlyChanging).withFastRender(renderFastChanging);
822
+ const categoryPage = collectionPage;
823
+ const init = makeJayInit().withServer(async () => {
824
+ console.log("[wix-stores-v1] Initializing Wix Stores V1 service...");
825
+ const wixClient = getService(WIX_CLIENT_SERVICE);
826
+ provideWixStoresV1Service(wixClient);
827
+ console.log("[wix-stores-v1] Server initialization complete");
828
+ return {
829
+ enableClientCart: true,
830
+ enableClientSearch: true
831
+ };
832
+ });
833
+ export {
834
+ WIX_CART_CONTEXT,
835
+ WIX_CART_SERVICE,
836
+ WIX_STORES_V1_CONTEXT,
837
+ WIX_STORES_V1_SERVICE_MARKER,
838
+ cartIndicator,
839
+ cartPage,
840
+ categoryList,
841
+ categoryPage,
842
+ collectionList,
843
+ collectionPage,
844
+ getCollections,
845
+ getProductBySlug,
846
+ init,
847
+ productPage,
848
+ productSearch,
849
+ provideWixCartContext,
850
+ provideWixCartService,
851
+ provideWixStoresV1Service,
852
+ searchProducts
853
+ };