@jay-framework/wix-stores 0.16.2 → 0.16.4

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.
@@ -27,7 +27,7 @@ function getProductsV3Client(wixClient) {
27
27
  }
28
28
  return instances.productsV3ClientInstance;
29
29
  }
30
- const WIX_STORES_CONTEXT = createJayContext();
30
+ const WIX_STORES_CONTEXT = createJayContext("wix:stores");
31
31
  function provideWixStoresContext() {
32
32
  const wixClientContext = useGlobalContext(WIX_CLIENT_CONTEXT);
33
33
  const wixClient = wixClientContext.client;
package/dist/index.d.ts CHANGED
@@ -420,6 +420,40 @@ declare function buildCategoryUrl(urls: UrlTemplates, tree: CategoryTree, catego
420
420
  /** Variant stock map: colorChoiceId -> textChoiceId -> inStock */
421
421
  type VariantStockMap = Record<string, Record<string, boolean>>;
422
422
 
423
+ /**
424
+ * Data Extension Schema → Contract Tag Utilities
425
+ *
426
+ * Converts Wix Data Extension JSON Schema properties to jay-contract YAML tags.
427
+ * Used to materialize the product-page contract with site-specific custom fields.
428
+ *
429
+ * Design Log #16
430
+ */
431
+ /** A single property from the JSON Schema returned by listDataExtensionSchemas */
432
+ interface JsonSchemaProperty {
433
+ type: string;
434
+ items?: JsonSchemaProperty & {
435
+ properties?: Record<string, JsonSchemaProperty>;
436
+ };
437
+ properties?: Record<string, JsonSchemaProperty>;
438
+ maxLength?: number;
439
+ maxItems?: number;
440
+ /** Wix extension metadata — ignored for contract generation */
441
+ 'x-wix-permissions'?: unknown;
442
+ 'x-wix-created-date'?: string;
443
+ 'x-wix-filterable'?: boolean;
444
+ }
445
+ /** Schema returned by listDataExtensionSchemas for a single namespace */
446
+ interface DataExtensionSchema {
447
+ fqdn?: string | null;
448
+ namespace?: string | null;
449
+ jsonSchema?: {
450
+ properties?: Record<string, JsonSchemaProperty>;
451
+ additionalProperties?: boolean;
452
+ } | null;
453
+ _id?: string | null;
454
+ revision?: string | null;
455
+ }
456
+
423
457
  interface WixStoresService {
424
458
  products: BuildDescriptors<typeof productsV3, {}>;
425
459
  categories: BuildDescriptors<typeof categories, {}>;
@@ -433,6 +467,8 @@ interface WixStoresService {
433
467
  getCategoryTree(): Promise<CategoryTree>;
434
468
  /** Get cached product customizations (options with choices). Lazily loaded. */
435
469
  getCustomizations(): Promise<Customization[]>;
470
+ /** Get cached data extension schemas for products. Lazily loaded. */
471
+ getDataExtensionSchemas(): Promise<DataExtensionSchema[]>;
436
472
  }
437
473
  /**
438
474
  * Server service marker for Wix Stores.
@@ -982,4 +1018,19 @@ declare function setupWixStores(ctx: PluginSetupContext): Promise<PluginSetupRes
982
1018
  */
983
1019
  declare function generateWixStoresReferences(ctx: PluginReferencesContext): Promise<PluginReferencesResult>;
984
1020
 
985
- export { type CategoryListParams, type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, WIX_STORES_CONTEXT, WIX_STORES_SERVICE_MARKER, type WixStoresContext, type WixStoresInitData, type WixStoresService, type WixStoresServiceOptions, buildCategoryUrl, buildProductUrl, categoryList, findCategoryImage, findRootCategoryId, findRootCategorySlug, generateWixStoresReferences, getCategories, getProductBySlug, getVariantStock, init, productPage, productSearch, provideWixStoresService, searchProducts, setupWixStores };
1021
+ /**
1022
+ * Product Page Contract Generator
1023
+ *
1024
+ * Materializes the product-page contract by extending the base static contract
1025
+ * with site-specific data extension fields from the Wix Data Extension Schema API.
1026
+ *
1027
+ * Design Log #16
1028
+ */
1029
+ /**
1030
+ * Generator for the product-page contract.
1031
+ * Takes the base contract YAML and appends an extendedFields sub-contract
1032
+ * generated from the site's data extension schemas.
1033
+ */
1034
+ declare const generator: _jay_framework_fullstack_component.DynamicContractGenerator<[WixStoresService]>;
1035
+
1036
+ export { type CategoryListParams, type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, WIX_STORES_CONTEXT, WIX_STORES_SERVICE_MARKER, type WixStoresContext, type WixStoresInitData, type WixStoresService, type WixStoresServiceOptions, buildCategoryUrl, buildProductUrl, categoryList, findCategoryImage, findRootCategoryId, findRootCategorySlug, generateWixStoresReferences, getCategories, getProductBySlug, getVariantStock, init, productPage, generator as productPageContractGenerator, productSearch, provideWixStoresService, searchProducts, setupWixStores };
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { WIX_CART_CONTEXT, WIX_CART_SERVICE, cartIndicator, cartPage, provideWixCartContext, provideWixCartService } from "@jay-framework/wix-cart";
2
- import { createJayService, makeJayQuery, ActionError, makeJayStackComponent, RenderPipeline, makeJayInit } from "@jay-framework/fullstack-component";
2
+ import { createJayService, makeJayQuery, ActionError, makeJayStackComponent, RenderPipeline, makeJayInit, makeContractGenerator } from "@jay-framework/fullstack-component";
3
3
  import { customizationsV3, inventoryItemsV3, productsV3 } from "@wix/stores";
4
4
  import { categories } from "@wix/categories";
5
5
  import { registerService, getService } from "@jay-framework/stack-server-runtime";
6
+ import { schemas } from "@wix/data-extension-schema";
6
7
  import { createJayContext } from "@jay-framework/runtime";
7
8
  import "@jay-framework/component";
8
9
  import { WIX_CLIENT_SERVICE } from "@jay-framework/wix-server-client";
@@ -57,6 +58,7 @@ const WIX_STORES_SERVICE_MARKER = createJayService("Wix Store Service");
57
58
  function provideWixStoresService(wixClient, options) {
58
59
  let cachedTree = null;
59
60
  let cachedCustomizations = null;
61
+ let cachedExtensionSchemas = null;
60
62
  const categoriesClient = getCategoriesClient(wixClient);
61
63
  const customizationsClient = getCustomizationsV3Client(wixClient);
62
64
  const service = {
@@ -110,6 +112,27 @@ function provideWixStoresService(wixClient, options) {
110
112
  cachedCustomizations = [];
111
113
  }
112
114
  return cachedCustomizations;
115
+ },
116
+ async getDataExtensionSchemas() {
117
+ if (cachedExtensionSchemas) return cachedExtensionSchemas;
118
+ try {
119
+ const client = wixClient.use(schemas);
120
+ const result = await client.listDataExtensionSchemas(
121
+ "wix.stores.catalog.v3.product"
122
+ );
123
+ cachedExtensionSchemas = result?.dataExtensionSchemas ?? [];
124
+ const fieldCount = cachedExtensionSchemas.reduce(
125
+ (n, s) => n + Object.keys(s.jsonSchema?.properties ?? {}).length,
126
+ 0
127
+ );
128
+ console.log(
129
+ `[wix-stores] Loaded ${cachedExtensionSchemas.length} data extension schema(s), ${fieldCount} field(s)`
130
+ );
131
+ } catch (error) {
132
+ console.error("[wix-stores] Failed to load data extension schemas:", error);
133
+ cachedExtensionSchemas = [];
134
+ }
135
+ return cachedExtensionSchemas;
113
136
  }
114
137
  };
115
138
  registerService(WIX_STORES_SERVICE_MARKER, service);
@@ -1194,6 +1217,18 @@ var MediaType = /* @__PURE__ */ ((MediaType2) => {
1194
1217
  MediaType2[MediaType2["VIDEO"] = 1] = "VIDEO";
1195
1218
  return MediaType2;
1196
1219
  })(MediaType || {});
1220
+ function mapExtendedFields(product) {
1221
+ const raw = product.extendedFields?.namespaces?.["_user_fields"] ?? {};
1222
+ const result = {};
1223
+ for (const [key, value] of Object.entries(raw)) {
1224
+ if (Array.isArray(value)) {
1225
+ result[key] = value.map((item, i) => typeof item === "object" && item !== null ? { ...item, _index: i } : { value: item, _index: i });
1226
+ } else {
1227
+ result[key] = value;
1228
+ }
1229
+ }
1230
+ return result;
1231
+ }
1197
1232
  async function* loadProductParams([wixStores]) {
1198
1233
  const template = wixStores.urls.product;
1199
1234
  const needsPrefix = template.includes("{prefix}");
@@ -1402,7 +1437,8 @@ async function renderSlowlyChanging$1(props, wixStores) {
1402
1437
  productType: mapProductType(productType),
1403
1438
  options: mapOptionsToSlowVS(options),
1404
1439
  infoSections: mapInfoSections(infoSections),
1405
- modifiers: mapModifiersToSlowVS(modifiers)
1440
+ modifiers: mapModifiersToSlowVS(modifiers),
1441
+ extendedFields: mapExtendedFields(product)
1406
1442
  },
1407
1443
  headTags: mapSeoHeadTags(seoData),
1408
1444
  carryForward: {
@@ -1516,7 +1552,7 @@ async function renderSlowlyChanging(props, wixStores) {
1516
1552
  });
1517
1553
  }
1518
1554
  const categoryList = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging);
1519
- const WIX_STORES_CONTEXT = createJayContext();
1555
+ const WIX_STORES_CONTEXT = createJayContext("wix:stores");
1520
1556
  function loadWixStoresConfig() {
1521
1557
  const configPath = path.join(process.cwd(), "config", ".wix-stores.yaml");
1522
1558
  const defaults = {
@@ -1665,11 +1701,258 @@ async function generateWixStoresReferences(ctx) {
1665
1701
  ),
1666
1702
  "utf-8"
1667
1703
  );
1704
+ let extensionFieldCount = 0;
1705
+ try {
1706
+ const extensionSchemas = await storesService.getDataExtensionSchemas();
1707
+ const userFieldsSchema = extensionSchemas.find(
1708
+ (s) => s.namespace === "_user_fields"
1709
+ );
1710
+ const properties = userFieldsSchema?.jsonSchema?.properties;
1711
+ if (properties && Object.keys(properties).length > 0) {
1712
+ extensionFieldCount = Object.keys(properties).length;
1713
+ const extensionPath = path.join(ctx.referencesDir, "data-extension-fields.yaml");
1714
+ fs.writeFileSync(
1715
+ extensionPath,
1716
+ yaml.dump(
1717
+ {
1718
+ _description: "Product data extension fields (custom fields defined in Wix dashboard).",
1719
+ fqdn: "wix.stores.v3.product",
1720
+ namespace: "_user_fields",
1721
+ fieldCount: extensionFieldCount,
1722
+ fields: Object.fromEntries(
1723
+ Object.entries(properties).map(([key, prop]) => [
1724
+ key,
1725
+ { type: prop.type }
1726
+ ])
1727
+ )
1728
+ },
1729
+ { indent: 2, lineWidth: 120, noRefs: true }
1730
+ ),
1731
+ "utf-8"
1732
+ );
1733
+ }
1734
+ } catch (error) {
1735
+ console.error("[wix-stores] Failed to fetch data extension schemas:", error);
1736
+ }
1737
+ const referencesCreated = [`agent-kit/references/${ctx.pluginName}/categories.yaml`];
1738
+ if (extensionFieldCount > 0) {
1739
+ referencesCreated.push(`agent-kit/references/${ctx.pluginName}/data-extension-fields.yaml`);
1740
+ }
1668
1741
  return {
1669
- referencesCreated: [`agent-kit/references/${ctx.pluginName}/categories.yaml`],
1670
- message: `${allCategories.length} categories (${roots.length} root)`
1742
+ referencesCreated,
1743
+ message: `${allCategories.length} categories (${roots.length} root), ${extensionFieldCount} extension fields`
1671
1744
  };
1672
1745
  }
1746
+ function jsonTypeToContractType(type) {
1747
+ switch (type) {
1748
+ case "boolean":
1749
+ return "boolean";
1750
+ case "number":
1751
+ case "integer":
1752
+ return "number";
1753
+ default:
1754
+ return "string";
1755
+ }
1756
+ }
1757
+ function dataTag(key, type, indent) {
1758
+ const prefix = " ".repeat(indent);
1759
+ return `${prefix}- {tag: ${key}, type: data, dataType: ${type}}`;
1760
+ }
1761
+ function objectSubContract(key, properties, repeated, indent) {
1762
+ const prefix = " ".repeat(indent);
1763
+ const innerTags = jsonSchemaToContractTags(properties, indent + 2);
1764
+ if (repeated) {
1765
+ const indexTag = dataTag("_index", "number", indent + 2);
1766
+ return `${prefix}- tag: ${key}
1767
+ ${prefix} type: sub-contract
1768
+ ${prefix} repeated: true
1769
+ ${prefix} trackBy: _index
1770
+ ${prefix} description: ${key}
1771
+ ${prefix} tags:
1772
+ ${indexTag}
1773
+ ${innerTags.join("\n")}`;
1774
+ }
1775
+ return `${prefix}- tag: ${key}
1776
+ ${prefix} type: sub-contract
1777
+ ${prefix} description: ${key}
1778
+ ${prefix} tags:
1779
+ ${innerTags.join("\n")}`;
1780
+ }
1781
+ function jsonSchemaToContractTags(properties, indent = 4) {
1782
+ const tags = [];
1783
+ for (const [key, prop] of Object.entries(properties)) {
1784
+ switch (prop.type) {
1785
+ case "string":
1786
+ case "boolean":
1787
+ case "number":
1788
+ case "integer":
1789
+ tags.push(dataTag(key, jsonTypeToContractType(prop.type), indent));
1790
+ break;
1791
+ case "array": {
1792
+ const items = prop.items;
1793
+ if (!items) {
1794
+ tags.push(dataTag(key, "string", indent));
1795
+ } else if (items.type === "object" && items.properties) {
1796
+ tags.push(objectSubContract(key, items.properties, true, indent));
1797
+ } else {
1798
+ tags.push(dataTag(key, jsonTypeToContractType(items.type || "string"), indent));
1799
+ }
1800
+ break;
1801
+ }
1802
+ case "object":
1803
+ if (prop.properties) {
1804
+ tags.push(objectSubContract(key, prop.properties, false, indent));
1805
+ } else {
1806
+ tags.push(dataTag(key, "string", indent));
1807
+ }
1808
+ break;
1809
+ default:
1810
+ tags.push(dataTag(key, "string", indent));
1811
+ break;
1812
+ }
1813
+ }
1814
+ return tags;
1815
+ }
1816
+ function buildExtendedFieldsSubContract(schemas2, indent = 2) {
1817
+ const userFieldsSchema = schemas2.find((s) => s.namespace === "_user_fields");
1818
+ const properties = userFieldsSchema?.jsonSchema?.properties;
1819
+ if (!properties || Object.keys(properties).length === 0) {
1820
+ return null;
1821
+ }
1822
+ const prefix = " ".repeat(indent);
1823
+ const innerTags = jsonSchemaToContractTags(properties, indent + 2);
1824
+ return `${prefix}- tag: extendedFields
1825
+ ${prefix} type: sub-contract
1826
+ ${prefix} description: Custom product fields from data extension schema
1827
+ ${prefix} tags:
1828
+ ${innerTags.join("\n")}`;
1829
+ }
1830
+ const BASE_CONTRACT_YAML = `name: product-page
1831
+ description: Full product detail page with variants, options, media gallery, and add-to-cart. Use for individual product pages.
1832
+ params:
1833
+ slug: string
1834
+ prefix: string?
1835
+ category: string?
1836
+ tags:
1837
+ - {tag: _id, type: data, dataType: string, description: Product GUID}
1838
+ - {tag: productName, type: data, dataType: string, required: true, description: Product name}
1839
+
1840
+ - tag: mediaGallery
1841
+ type: sub-contract
1842
+ phase: fast+interactive
1843
+ link: "@jay-framework/wix-stores/media-gallery"
1844
+
1845
+ - {tag: description, type: data, dataType: string, description: Product description}
1846
+ - {tag: brand, type: data, dataType: string, description: Brand name}
1847
+ - {tag: ribbon, type: data, dataType: string, description: "Ribbon text (e.g., \\"New\\", \\"Sale\\")"}
1848
+ - {tag: productType, type: variant, dataType: "enum (PHYSICAL | DIGITAL)", description: Product type }
1849
+
1850
+ - {tag: sku, type: data, dataType: string, phase: fast+interactive, description: Product SKU, or chosen variant SKU}
1851
+ - {tag: price, type: data, dataType: string, phase: fast+interactive, description: The product or variant price}
1852
+ - {tag: strikethroughPrice, type: data, dataType: string, phase: fast+interactive, description: A Strikethrough product price for sales}
1853
+ - {tag: pricePerUnit, type: data, dataType: string, phase: fast+interactive, description: formatted price per unit, if used}
1854
+ - {tag: stockStatus, type: variant, dataType: "enum (OUT_OF_STOCK | IN_STOCK)", phase: fast+interactive, description: indicator if the product or current variant are in stock }
1855
+
1856
+ - tag: quantity
1857
+ type: sub-contract
1858
+ description: Quantity selection controls
1859
+ tags:
1860
+ - {tag: decrementButton, type: interactive, elementType: HTMLButtonElement, description: Button to decrease quantity}
1861
+ - {tag: incrementButton, type: interactive, elementType: HTMLButtonElement, description: Button to increase quantity}
1862
+ - {tag: quantity, type: [data, interactive], dataType: number, elementType: HTMLInputElement, description: Selected Quantity and Direct quantity input field}
1863
+
1864
+ # Call to action
1865
+ - {tag: addToCartButton, type: interactive, elementType: HTMLButtonElement, required: true, description: Add product to cart button}
1866
+ - {tag: buyNowButton, type: interactive, elementType: HTMLButtonElement, required: true, description: Buy now button}
1867
+ - {tag: actionsEnabled, type: variant, dataType: boolean, phase: fast+interactive, description: should the add to cart and buy now buttons be enabled}
1868
+ - {tag: isAddingToCart, type: variant, dataType: boolean, phase: fast+interactive, description: Whether an add-to-cart request is currently in progress}
1869
+
1870
+ - tag: options
1871
+ type: sub-contract
1872
+ repeated: true
1873
+ trackBy: _id
1874
+ description: Product customization options that generate variants
1875
+ tags:
1876
+ - {tag: _id, type: data, dataType: string, description: "Option GUID (customization ID)"}
1877
+ - {tag: name, type: data, dataType: string, description: "Option name (e.g., \\"Color\\", \\"Size\\")"}
1878
+ - {tag: optionRenderType, type: variant, dataType: "enum (TEXT_CHOICES | COLOR_SWATCH_CHOICES)", description: How the option should be rendered}
1879
+ - {tag: textChoice, type: interactive, elementType: HTMLSelectElement, description: dropdown for text choice}
1880
+ - {tag: textChoiceSelection, type: data, dataType: string, phase: fast+interactive, description: the selected text option}
1881
+
1882
+ - tag: choices
1883
+ type: sub-contract
1884
+ repeated: true
1885
+ trackBy: choiceId
1886
+ description: Available choices for this option
1887
+ tags:
1888
+ - {tag: choiceId, type: data, dataType: string, description: Choice GUID}
1889
+ - {tag: choiceType, type: variant, dataType: "enum (CHOICE_TEXT | ONE_COLOR)", description: Type of choice}
1890
+ - {tag: name, type: data, dataType: string, description: "Choice name (e.g., \\"Red\\", \\"Large\\")"}
1891
+ - {tag: colorCode, type: data, dataType: string, description: Color code in HEX format (for color choices)}
1892
+ - {tag: inStock, type: data, dataType: boolean, description: Whether at least one variant with this choice is in stock}
1893
+ - {tag: isSelected, type: variant, dataType: boolean, phase: fast+interactive, description: Whether this choice is currently selected (UI state)}
1894
+ - {tag: choiceButton, type: interactive, elementType: HTMLButtonElement, description: Button to select this choice}
1895
+
1896
+ # Additional info sections (from Wix Stores API)
1897
+ - tag: infoSections
1898
+ type: sub-contract
1899
+ repeated: true
1900
+ trackBy: _id
1901
+ description: Additional product information sections
1902
+ tags:
1903
+ - {tag: _id, type: data, dataType: string, description: Info section GUID}
1904
+ - {tag: title, type: data, dataType: string, description: Info section title}
1905
+ - {tag: plainDescription, type: data, dataType: string, description: Info section description in HTML}
1906
+
1907
+ - tag: modifiers
1908
+ type: sub-contract
1909
+ repeated: true
1910
+ trackBy: _id
1911
+ description: Product customization options that do not generate variants
1912
+ tags:
1913
+ - {tag: _id, type: data, dataType: string, description: "modifier id"}
1914
+ - {tag: name, type: data, dataType: string, description: "modifier name (e.g., \\"Color\\", \\"Size\\")"}
1915
+ - {tag: modifierType, type: variant, dataType: "enum (TEXT_CHOICES | COLOR_SWATCH_CHOICES | FREE_TEXT)", description: What type of modifier to use?}
1916
+ - {tag: textModifier, type: interactive, elementType: HTMLSelectElement, description: dropdown for text modifier}
1917
+ - {tag: textModifierSelection, type: data, dataType: string, phase: fast+interactive, description: the selected text modifier}
1918
+ - {tag: textInput, type: interactive, elementType: HTMLInputElement | HTMLAreaElement, description: text input for free text}
1919
+ - {tag: textInputLength, type: data, dataType: number, description: the limit on the length of free text}
1920
+ - {tag: textInputRequired, type: data, dataType: boolean, description: Is the free text input required?}
1921
+
1922
+ - tag: choices
1923
+ type: sub-contract
1924
+ repeated: true
1925
+ trackBy: choiceId
1926
+ description: Available choices for this Modifier
1927
+ tags:
1928
+ - {tag: choiceId, type: data, dataType: string, description: Choice GUID}
1929
+ - {tag: choiceType, type: variant, dataType: "enum (CHOICE_TEXT | ONE_COLOR)", description: Type of choice}
1930
+ - {tag: name, type: data, dataType: string, description: "Choice name (e.g., \\"Red\\", \\"Large\\")"}
1931
+ - {tag: colorCode, type: data, dataType: string, description: Color code in HEX format (for color choices)}
1932
+ - {tag: isSelected, type: variant, dataType: boolean, phase: fast+interactive, description: Whether this choice is currently selected (UI state)}
1933
+ - {tag: choiceButton, type: interactive, elementType: HTMLButtonElement, description: Button to select this choice}
1934
+
1935
+ # SEO data is injected into <head> via headTags (Design Log #127), not part of the contract view state.`;
1936
+ const generator = makeContractGenerator().withServices(WIX_STORES_SERVICE_MARKER).generateWith(async (wixStoresService) => {
1937
+ const schemas2 = await wixStoresService.getDataExtensionSchemas();
1938
+ const extendedFieldsBlock = buildExtendedFieldsSubContract(schemas2);
1939
+ let yaml2 = BASE_CONTRACT_YAML;
1940
+ if (extendedFieldsBlock) {
1941
+ yaml2 = yaml2 + "\n\n" + extendedFieldsBlock;
1942
+ }
1943
+ return [
1944
+ {
1945
+ yaml: yaml2,
1946
+ description: "Product page with data extension fields",
1947
+ metadata: {
1948
+ extendedFieldCount: schemas2.reduce(
1949
+ (count, s) => count + Object.keys(s.jsonSchema?.properties ?? {}).length,
1950
+ 0
1951
+ )
1952
+ }
1953
+ }
1954
+ ];
1955
+ });
1673
1956
  export {
1674
1957
  WIX_CART_CONTEXT,
1675
1958
  WIX_CART_SERVICE,
@@ -1689,6 +1972,7 @@ export {
1689
1972
  getVariantStock,
1690
1973
  init,
1691
1974
  productPage,
1975
+ generator as productPageContractGenerator,
1692
1976
  productSearch,
1693
1977
  provideWixCartContext,
1694
1978
  provideWixCartService,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/wix-stores",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "type": "module",
5
5
  "description": "Wix Stores API client for Jay Framework",
6
6
  "license": "Apache-2.0",
@@ -14,6 +14,8 @@
14
14
  "./client": "./dist/index.client.js",
15
15
  "./plugin.yaml": "./plugin.yaml",
16
16
  "./product-page.jay-contract": "./dist/contracts/product-page.jay-contract",
17
+ "./media.jay-contract": "./dist/contracts/media.jay-contract",
18
+ "./media-gallery.jay-contract": "./dist/contracts/media-gallery.jay-contract",
17
19
  "./product-search.jay-contract": "./dist/contracts/product-search.jay-contract",
18
20
  "./category-list.jay-contract": "./dist/contracts/category-list.jay-contract",
19
21
  "./search-products.jay-action": "./dist/actions/search-products.jay-action",
@@ -35,17 +37,18 @@
35
37
  "test": ":"
36
38
  },
37
39
  "dependencies": {
38
- "@jay-framework/component": "^0.16.2",
39
- "@jay-framework/fullstack-component": "^0.16.2",
40
- "@jay-framework/reactive": "^0.16.2",
41
- "@jay-framework/runtime": "^0.16.2",
42
- "@jay-framework/secure": "^0.16.2",
43
- "@jay-framework/stack-client-runtime": "^0.16.2",
44
- "@jay-framework/stack-server-runtime": "^0.16.2",
45
- "@jay-framework/wix-cart": "^0.16.2",
46
- "@jay-framework/wix-server-client": "^0.16.2",
47
- "@jay-framework/wix-utils": "^0.16.2",
40
+ "@jay-framework/component": "^0.16.4",
41
+ "@jay-framework/fullstack-component": "^0.16.4",
42
+ "@jay-framework/reactive": "^0.16.4",
43
+ "@jay-framework/runtime": "^0.16.4",
44
+ "@jay-framework/secure": "^0.16.4",
45
+ "@jay-framework/stack-client-runtime": "^0.16.4",
46
+ "@jay-framework/stack-server-runtime": "^0.16.4",
47
+ "@jay-framework/wix-cart": "^0.16.4",
48
+ "@jay-framework/wix-server-client": "^0.16.4",
49
+ "@jay-framework/wix-utils": "^0.16.4",
48
50
  "@wix/categories": "^1.0.185",
51
+ "@wix/data-extension-schema": "^1.0.221",
49
52
  "@wix/sdk": "^1.21.5",
50
53
  "@wix/sdk-runtime": "^1.0.11",
51
54
  "@wix/stores": "^1.0.742",
@@ -55,10 +58,10 @@
55
58
  "@babel/core": "^7.23.7",
56
59
  "@babel/preset-env": "^7.23.8",
57
60
  "@babel/preset-typescript": "^7.23.3",
58
- "@jay-framework/compiler-jay-stack": "^0.16.2",
59
- "@jay-framework/jay-cli": "^0.16.2",
60
- "@jay-framework/jay-stack-cli": "^0.16.2",
61
- "@jay-framework/vite-plugin": "^0.16.2",
61
+ "@jay-framework/compiler-jay-stack": "^0.16.4",
62
+ "@jay-framework/jay-cli": "^0.16.4",
63
+ "@jay-framework/jay-stack-cli": "^0.16.4",
64
+ "@jay-framework/vite-plugin": "^0.16.4",
62
65
  "nodemon": "^3.0.3",
63
66
  "rimraf": "^5.0.5",
64
67
  "tslib": "^2.6.2",
package/plugin.yaml CHANGED
@@ -2,10 +2,6 @@ name: wix-stores
2
2
  # No module field for NPM packages - uses package main export by default
3
3
 
4
4
  contracts:
5
- - name: product-page
6
- contract: product-page.jay-contract # Export subpath (matches package.json exports)
7
- component: productPage # Exported member name from index.ts
8
- description: Complete headless product page with server-side rendering and client interactivity
9
5
  - name: product-search
10
6
  contract: product-search.jay-contract
11
7
  component: productSearch
@@ -16,6 +12,13 @@ contracts:
16
12
  component: categoryList
17
13
  description: Category list listing the categories
18
14
 
15
+ # Dynamic contracts — materialized at setup time from site-specific data
16
+ dynamic_contracts:
17
+ # Product page — base contract extended with data extension fields
18
+ - prefix: 'product-page'
19
+ component: productPage
20
+ generator: productPageContractGenerator
21
+
19
22
  # Server actions (named exports from main module)
20
23
  actions:
21
24
  - name: searchProducts