@fragmentsx/client-core 0.3.0 → 0.4.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.
Files changed (44) hide show
  1. package/dist/createAreaManager.d.ts +18 -0
  2. package/dist/createAreaManager.d.ts.map +1 -0
  3. package/dist/fragmentsClient.d.ts +0 -2
  4. package/dist/fragmentsClient.d.ts.map +1 -1
  5. package/dist/index.cjs.js +223 -225
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.es.js +223 -225
  9. package/dist/plugins/fetch/areaQueries.test.d.ts +2 -0
  10. package/dist/plugins/fetch/areaQueries.test.d.ts.map +1 -0
  11. package/dist/plugins/fetch/index.d.ts +10 -7
  12. package/dist/plugins/fetch/index.d.ts.map +1 -1
  13. package/dist/plugins/fetch/restFetcher.d.ts +6 -0
  14. package/dist/plugins/fetch/restFetcher.d.ts.map +1 -0
  15. package/dist/plugins/fetch/restFetcher.test.d.ts +2 -0
  16. package/dist/plugins/fetch/restFetcher.test.d.ts.map +1 -0
  17. package/dist/plugins/fonts/index.d.ts.map +1 -1
  18. package/dist/plugins/fonts/index.test.d.ts +2 -0
  19. package/dist/plugins/fonts/index.test.d.ts.map +1 -0
  20. package/dist/plugins/fragments/index.d.ts.map +1 -1
  21. package/dist/plugins/load/index.d.ts +1 -1
  22. package/dist/plugins/load/index.d.ts.map +1 -1
  23. package/dist/plugins/metrics/globalMetrics.d.ts +8 -1
  24. package/dist/plugins/metrics/globalMetrics.d.ts.map +1 -1
  25. package/dist/plugins/metrics/index.d.ts.map +1 -1
  26. package/dist/plugins/properties/index.d.ts +17 -0
  27. package/dist/plugins/properties/index.d.ts.map +1 -0
  28. package/dist/plugins/properties/index.test.d.ts +2 -0
  29. package/dist/plugins/properties/index.test.d.ts.map +1 -0
  30. package/dist/testing/createTestFragmentsClient.d.ts +4 -0
  31. package/dist/testing/createTestFragmentsClient.d.ts.map +1 -1
  32. package/package.json +1 -1
  33. package/dist/plugins/fetch/fetcher.d.ts +0 -8
  34. package/dist/plugins/fetch/fetcher.d.ts.map +0 -1
  35. package/dist/plugins/fetch/fetcher.test.d.ts +0 -2
  36. package/dist/plugins/fetch/fetcher.test.d.ts.map +0 -1
  37. package/dist/plugins/fetch/queries/AreaListQuery.d.ts +0 -43
  38. package/dist/plugins/fetch/queries/AreaListQuery.d.ts.map +0 -1
  39. package/dist/plugins/fetch/queries/AreaQuery.d.ts +0 -24
  40. package/dist/plugins/fetch/queries/AreaQuery.d.ts.map +0 -1
  41. package/dist/plugins/fetch/queries/FragmentQuery.d.ts +0 -31
  42. package/dist/plugins/fetch/queries/FragmentQuery.d.ts.map +0 -1
  43. package/dist/plugins/fetch/queries/parts.d.ts +0 -5
  44. package/dist/plugins/fetch/queries/parts.d.ts.map +0 -1
@@ -0,0 +1,18 @@
1
+ declare module "@graph-state/core" {
2
+ interface GraphState {
3
+ $area?: {
4
+ areaId: number;
5
+ campaignId?: number;
6
+ variantId?: number;
7
+ };
8
+ }
9
+ }
10
+ interface CreateAreaManagerOptions {
11
+ areaId: number;
12
+ campaignId?: number;
13
+ variantId?: number;
14
+ areaProperties?: any[];
15
+ }
16
+ export declare const createAreaManager: (options: CreateAreaManagerOptions) => import('@graph-state/core').GraphState<import('@graph-state/core').SystemFields, "AreaManager">;
17
+ export {};
18
+ //# sourceMappingURL=createAreaManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAreaManager.d.ts","sourceRoot":"","sources":["../src/createAreaManager.ts"],"names":[],"mappings":"AAKA,OAAO,QAAQ,mBAAmB,CAAC;IACjC,UAAU,UAAU;QAClB,KAAK,CAAC,EAAE;YACN,MAAM,EAAE,MAAM,CAAC;YACf,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB,CAAC;KACH;CACF;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC;CACxB;AAYD,eAAO,MAAM,iBAAiB,YAAa,wBAAwB,oGA0BlE,CAAC"}
@@ -2,7 +2,6 @@ import { Plugin } from '@graph-state/core';
2
2
  declare module "@graph-state/core" {
3
3
  interface GraphState {
4
4
  env: {
5
- isSelf: boolean;
6
5
  apiToken: string;
7
6
  backendEndpoint: string;
8
7
  referer?: string;
@@ -13,7 +12,6 @@ interface Options {
13
12
  apiToken: string;
14
13
  referer?: string;
15
14
  backendEndpoint?: string;
16
- isSelf?: boolean;
17
15
  fragmentPlugins?: Plugin[];
18
16
  }
19
17
  export declare const PLUGIN_TYPES: {
@@ -1 +1 @@
1
- {"version":3,"file":"fragmentsClient.d.ts","sourceRoot":"","sources":["../src/fragmentsClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAYxD,OAAO,QAAQ,mBAAmB,CAAC;IACjC,UAAU,UAAU;QAClB,GAAG,EAAE;YACH,MAAM,EAAE,OAAO,CAAC;YAChB,QAAQ,EAAE,MAAM,CAAC;YACjB,eAAe,EAAE,MAAM,CAAC;YACxB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH;CACF;AAED,UAAU,OAAO;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY;;;;CAIxB,CAAC;AAEF,eAAO,MAAM,qBAAqB,YAAa,OAAO,sGAkCrD,CAAC"}
1
+ {"version":3,"file":"fragmentsClient.d.ts","sourceRoot":"","sources":["../src/fragmentsClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAaxD,OAAO,QAAQ,mBAAmB,CAAC;IACjC,UAAU,UAAU;QAClB,GAAG,EAAE;YACH,QAAQ,EAAE,MAAM,CAAC;YACjB,eAAe,EAAE,MAAM,CAAC;YACxB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH;CACF;AAED,UAAU,OAAO;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY;;;;CAIxB,CAAC;AAEF,eAAO,MAAM,qBAAqB,YAAa,OAAO,sGAgCrD,CAAC"}
package/dist/index.cjs.js CHANGED
@@ -1690,100 +1690,48 @@ const CssOverrideSchema = /* @__PURE__ */ object({
1690
1690
  const BASE_HEADERS = {
1691
1691
  "Content-Type": "application/json"
1692
1692
  };
1693
- const createFetcher = (baseUrl, defaultHeaders = {}) => {
1693
+ const createRestFetcher = (baseUrl, defaultHeaders = {}) => {
1694
1694
  const cache = /* @__PURE__ */ new Map();
1695
1695
  const inflightRequests = /* @__PURE__ */ new Map();
1696
- const getCacheKey = (query2, variables, options) => JSON.stringify({ query: query2, variables, options });
1697
- const query = async (query2, variables = {}, options = {}) => {
1698
- const cacheKey = getCacheKey(query2, variables, options);
1699
- if (cache.has(cacheKey)) {
1700
- return cache.get(cacheKey);
1696
+ const get = (url) => {
1697
+ const fullUrl = `${baseUrl}${url}`;
1698
+ if (cache.has(fullUrl)) {
1699
+ return Promise.resolve(cache.get(fullUrl));
1701
1700
  }
1702
- if (inflightRequests.has(cacheKey)) {
1703
- return inflightRequests.get(cacheKey);
1701
+ if (inflightRequests.has(fullUrl)) {
1702
+ return inflightRequests.get(fullUrl);
1704
1703
  }
1705
- const request = fetch(baseUrl, {
1706
- ...options,
1707
- method: "POST",
1708
- body: JSON.stringify({ query: query2, variables }),
1709
- credentials: "include",
1704
+ const request = fetch(fullUrl, {
1705
+ method: "GET",
1710
1706
  headers: {
1711
1707
  ...BASE_HEADERS,
1712
- ...defaultHeaders,
1713
- ...options.headers
1708
+ ...defaultHeaders
1714
1709
  }
1715
1710
  }).then(async (res) => {
1716
1711
  if (!res.ok) {
1717
- if (process.env.NODE_ENV === "production") {
1718
- console.error(`Fetch error: ${res.status}`);
1719
- return null;
1720
- }
1721
- throw new Error(`Fetch error: ${res.status}`);
1712
+ throw new Error(`Fetch error: ${res.status} ${res.statusText}`);
1722
1713
  }
1723
- const data = await res.json();
1724
- if (!query2.includes("mutation")) {
1725
- cache.set(cacheKey, data);
1714
+ let data;
1715
+ try {
1716
+ data = await res.json();
1717
+ } catch {
1718
+ return null;
1726
1719
  }
1720
+ cache.set(fullUrl, data);
1727
1721
  return data;
1728
1722
  }).finally(() => {
1729
- inflightRequests.delete(cacheKey);
1723
+ inflightRequests.delete(fullUrl);
1730
1724
  });
1731
- inflightRequests.set(cacheKey, request);
1725
+ inflightRequests.set(fullUrl, request);
1732
1726
  return request;
1733
1727
  };
1734
- const invalidate = (endpoint, options) => {
1735
- cache.delete(getCacheKey(endpoint, options));
1728
+ const invalidate = (url) => {
1729
+ cache.delete(`${baseUrl}${url}`);
1736
1730
  };
1737
- const clearCache = () => cache.clear();
1738
- return { query, invalidate, clearCache };
1739
- };
1740
- const googleFonts = `googleFonts {
1741
- id
1742
- variants
1743
- subsets
1744
- family
1745
- version
1746
- files {
1747
- url
1748
- variant
1749
- }
1750
- category
1751
- }`;
1752
- const linkedCssChunk = `linkedCssChunk {
1753
- id
1754
- content
1755
- }`;
1756
- const linkedFragments = `{
1757
- id
1758
- document
1759
- ${googleFonts}
1760
- ${linkedCssChunk}
1761
- }`;
1762
- const fragment = `
1763
- {
1764
- id
1765
- document
1766
- linkedFragments ${linkedFragments}
1767
- ${googleFonts}
1768
- ${linkedCssChunk}
1769
- }
1770
- `;
1771
- const getFragmentQuery = (fragmentId, isSelf) => {
1772
- return {
1773
- query: isSelf ? `
1774
- query FragmentDocument($fragmentId: Int!) {
1775
- fragment(fragmentIds: [$fragmentId]) ${fragment}
1776
- }
1777
- ` : `
1778
- query FragmentDocument($fragmentId: Int!) {
1779
- clientFragment(fragmentId: $fragmentId) ${fragment}
1780
- }
1781
- }`,
1782
- variables: {
1783
- fragmentId
1784
- },
1785
- _type: null
1731
+ const clearCache = () => {
1732
+ cache.clear();
1786
1733
  };
1734
+ return { get, invalidate, clearCache };
1787
1735
  };
1788
1736
  var isObject = (input) => {
1789
1737
  return typeof input === "object" && input !== null && !Array.isArray(input);
@@ -1798,6 +1746,7 @@ var createConstants = (...constants) => {
1798
1746
  };
1799
1747
  var noop = () => void 0;
1800
1748
  var isBrowser_default = typeof window !== "undefined";
1749
+ var generateId = () => Math.random().toString(16).slice(2);
1801
1750
  var getKey = (v) => isKey(v) ? v.slice(1) : null;
1802
1751
  var isKey = (v) => typeof v === "string" && v.startsWith("$");
1803
1752
  function hashGenerator(layerKey) {
@@ -1955,159 +1904,88 @@ const fetchBeacon = (baseUrl) => {
1955
1904
  sendBeacon
1956
1905
  };
1957
1906
  };
1958
- const getAreaListQuery = (areaCodes) => {
1959
- return {
1960
- query: `query($areaCodes: [String!]!) {
1961
- clientAreas(areaCodes: $areaCodes) {
1962
- areaId
1963
- campaignId
1964
- areaProperties
1965
- projectProperties
1966
- font {
1967
- id
1968
- variants
1969
- subsets
1970
- family
1971
- version
1972
- files {
1973
- url
1974
- variant
1975
- }
1976
- category
1977
- }
1978
- variant {
1979
- id
1980
- fragment {
1981
- props
1982
- fragment ${fragment}
1983
- }
1984
- }
1985
- }
1986
- }`,
1987
- variables: {
1988
- areaCodes
1989
- }
1990
- };
1991
- };
1992
1907
  const fetchPlugin = (state) => {
1993
- var _a, _b, _c, _d;
1994
- const isSelf = ((_a = state == null ? void 0 : state.env) == null ? void 0 : _a.isSelf) ?? false;
1995
- const url = (_b = state == null ? void 0 : state.env) == null ? void 0 : _b.backendEndpoint;
1996
- const apiToken = (_c = state == null ? void 0 : state.env) == null ? void 0 : _c.apiToken;
1997
- const referer = (_d = state == null ? void 0 : state.env) == null ? void 0 : _d.referer;
1908
+ var _a, _b, _c;
1909
+ const url = (_a = state == null ? void 0 : state.env) == null ? void 0 : _a.backendEndpoint;
1910
+ const apiToken = (_b = state == null ? void 0 : state.env) == null ? void 0 : _b.apiToken;
1911
+ const referer = (_c = state == null ? void 0 : state.env) == null ? void 0 : _c.referer;
1998
1912
  let headers = {
1999
- Authorization: `Bearer ${apiToken}`
1913
+ "X-Api-Key": apiToken
2000
1914
  };
2001
1915
  if (referer) {
2002
1916
  headers.Referer = referer;
2003
1917
  }
2004
- const fetcher = createFetcher(url, headers);
1918
+ const restFetcher = createRestFetcher(url, headers);
2005
1919
  const beaconFetcher = fetchBeacon();
2006
- const registerFragmentDocument = (fragmentId, fragment2) => {
2007
- var _a2, _b2;
2008
- const fragmentDocument = fragment2 == null ? void 0 : fragment2.document;
1920
+ const registerFragmentDocument = (fragmentId, fragment) => {
1921
+ const fragmentDocument = fragment == null ? void 0 : fragment.document;
2009
1922
  if (!fragmentDocument) {
2010
1923
  console.error("Empty document");
2011
1924
  return null;
2012
1925
  }
2013
- if (fragment2) {
2014
- state.$fetch.cacheDocuments.set(fragmentId, fragmentDocument);
2015
- if (Array.isArray(fragment2.linkedFragments)) {
2016
- fragment2.linkedFragments.forEach(
2017
- (linkedFragment) => registerFragmentDocument(linkedFragment.id, linkedFragment)
2018
- );
2019
- }
2020
- if (Array.isArray(fragment2.linkedCssChunk)) {
2021
- fragment2.linkedCssChunk.forEach(
2022
- (linkedChunk) => state.$fetch.cacheCssChunks.set(linkedChunk.id, linkedChunk.content)
2023
- );
2024
- }
2025
- if ("$fonts" in state) {
2026
- (_b2 = fragment2 == null ? void 0 : fragment2.googleFonts) == null ? void 0 : _b2.forEach((_a2 = state.$fonts) == null ? void 0 : _a2.registerFont);
2027
- }
2028
- return fragmentDocument;
2029
- }
2030
- return null;
2031
- };
2032
- const queryFragment = async (fragmentId) => {
2033
- var _a2;
2034
- if (!apiToken || !fragmentId) return null;
2035
- if (state.$fetch.cacheDocuments.has(fragmentId)) {
2036
- return state.$fetch.cacheDocuments.get(fragmentId);
2037
- }
2038
- const fragmentQuery = getFragmentQuery(fragmentId, isSelf);
2039
- const response = await fetcher.query(
2040
- fragmentQuery.query,
2041
- fragmentQuery.variables,
2042
- { referrerPolicy: "unsafe-url" }
2043
- );
2044
- let fragment2 = null;
2045
- if (!!(response == null ? void 0 : response.data) && "clientFragment" in response.data) {
2046
- fragment2 = response.data.clientFragment;
1926
+ state.$fetch.cacheDocuments.set(fragmentId, fragmentDocument);
1927
+ if (fragment.linkedFragments !== void 0) {
1928
+ fragment.linkedFragments.forEach((linked) => {
1929
+ if ((linked == null ? void 0 : linked.id) && (linked == null ? void 0 : linked.document)) {
1930
+ state.$fetch.cacheDocuments.set(linked.id, linked.document);
1931
+ }
1932
+ });
2047
1933
  }
2048
- if (!!(response == null ? void 0 : response.data) && "fragment" in response.data) {
2049
- fragment2 = (_a2 = response.data.fragment) == null ? void 0 : _a2.at(0);
1934
+ if (Array.isArray(fragment.fragmentCssChunks)) {
1935
+ fragment.fragmentCssChunks.forEach(({ cssChunk }) => {
1936
+ if (cssChunk) {
1937
+ state.$fetch.cacheCssChunks.set(cssChunk.id, cssChunk.content);
1938
+ }
1939
+ });
2050
1940
  }
2051
- return registerFragmentDocument(fragmentId, fragment2);
1941
+ return fragmentDocument;
2052
1942
  };
2053
- const queryArea = async (areaCode) => {
2054
- return queryAreaList([areaCode]).then((res) => res == null ? void 0 : res.at(0));
2055
- };
2056
- const queryAreaList = async (areaCodes2) => {
2057
- var _a2;
2058
- if (!apiToken || !areaCodes2) return null;
2059
- const nonLoadedAreas = areaCodes2.filter(
1943
+ const queryAreaList = async (areaCodes) => {
1944
+ if (!apiToken || !(areaCodes == null ? void 0 : areaCodes.length)) return [];
1945
+ const nonLoadedCodes = areaCodes.filter(
2060
1946
  (code) => !state.$fetch.cacheAreaDocuments.has(code)
2061
1947
  );
2062
- if (!nonLoadedAreas.length) {
2063
- return areaCodes2.map(state.$fetch.cacheAreaDocuments.get);
1948
+ if (nonLoadedCodes.length > 0) {
1949
+ await Promise.all(
1950
+ nonLoadedCodes.map(async (code) => {
1951
+ var _a2, _b2, _c2, _d;
1952
+ const dto = await restFetcher.get(`/api/area/${code}`);
1953
+ if (!dto) return;
1954
+ const fragment = (_a2 = dto.variant) == null ? void 0 : _a2.fragment;
1955
+ if (fragment) {
1956
+ registerFragmentDocument(fragment.id, fragment);
1957
+ }
1958
+ if ("$fonts" in state && dto.font) {
1959
+ (_b2 = state.$fonts) == null ? void 0 : _b2.registerFont(dto.font);
1960
+ }
1961
+ const entity = {
1962
+ fragmentId: fragment == null ? void 0 : fragment.id,
1963
+ props: ((_c2 = dto.variant) == null ? void 0 : _c2.props) ?? {},
1964
+ font: dto.font,
1965
+ areaId: dto.areaId,
1966
+ campaignId: dto.campaignId,
1967
+ variantId: (_d = dto.variant) == null ? void 0 : _d.id
1968
+ };
1969
+ state.$fetch.cacheAreaDocuments.set(code, entity);
1970
+ })
1971
+ );
2064
1972
  }
2065
- const areaQuery = getAreaListQuery(areaCodes2);
2066
- const response = await fetcher.query(
2067
- areaQuery.query,
2068
- areaQuery.variables,
2069
- { referrerPolicy: "unsafe-url" }
1973
+ return areaCodes.map(
1974
+ (code) => state.$fetch.cacheAreaDocuments.get(code) ?? null
2070
1975
  );
2071
- const areas = (_a2 = response == null ? void 0 : response.data) == null ? void 0 : _a2.clientAreas;
2072
- if (areas) {
2073
- areas.forEach((area, index2) => {
2074
- var _a3;
2075
- const areaCode = areaCodes2 == null ? void 0 : areaCodes2.at(index2);
2076
- const areaFragment = area.variant.fragment.fragment;
2077
- registerFragmentDocument(areaFragment.id, areaFragment);
2078
- const resultProps = [
2079
- ...area.projectProperties ?? [],
2080
- ...area.areaProperties ?? []
2081
- ].reduce((acc, prop) => {
2082
- acc[prop._id] = prop.defaultValue;
2083
- return acc;
2084
- }, area.variant.fragment.props);
2085
- const entity = {
2086
- areaId: area.areaId,
2087
- campaignId: area.campaignId,
2088
- variantId: area.variant.id,
2089
- fragmentId: area.variant.fragment.fragment.id,
2090
- font: area.font,
2091
- props: resultProps
2092
- };
2093
- if ("$fonts" in state) {
2094
- (_a3 = state.$fonts) == null ? void 0 : _a3.registerFont(area.font);
2095
- }
2096
- state.$fetch.cacheAreaDocuments.set(areaCode, entity);
2097
- });
2098
- return areaCodes2.map((code) => state.$fetch.cacheAreaDocuments.get(code));
2099
- }
2100
- return null;
1976
+ };
1977
+ const queryArea = async (areaCode) => {
1978
+ return queryAreaList([areaCode]).then((res) => (res == null ? void 0 : res.at(0)) ?? null);
2101
1979
  };
2102
1980
  state.$fetch = {
2103
1981
  cacheCssChunks: /* @__PURE__ */ new Map(),
2104
1982
  cacheDocuments: /* @__PURE__ */ new Map(),
2105
1983
  cacheAreaDocuments: /* @__PURE__ */ new Map(),
2106
- queryFragment,
1984
+ registerFragmentDocument,
2107
1985
  queryArea,
2108
1986
  queryAreaList,
2109
- query: fetcher.query,
2110
1987
  sendBeacon: beaconFetcher.sendBeacon,
1988
+ get: restFetcher.get,
2111
1989
  readCssChunk: (id) => state.$fetch.cacheCssChunks.get(id) ?? null,
2112
1990
  readFragment: (fragmentId) => state.$fetch.cacheDocuments.get(fragmentId) ?? null,
2113
1991
  readArea: (areaCode) => state.$fetch.cacheAreaDocuments.get(areaCode) ?? null
@@ -2410,6 +2288,84 @@ const scopesPlugin = (state) => {
2410
2288
  };
2411
2289
  return state;
2412
2290
  };
2291
+ const PROPERTIES_ROOT_KEY = "PropertiesRoot:root";
2292
+ const propertiesPlugin = (state) => {
2293
+ const hydrate = (properties) => {
2294
+ if (!Array.isArray(properties)) return;
2295
+ const keys = [];
2296
+ for (const prop of properties) {
2297
+ if (!prop || !prop._id) continue;
2298
+ const key = `${index.nodes.Variable}:${prop._id}`;
2299
+ state.mutate(
2300
+ { ...prop, _type: index.nodes.Variable, _id: String(prop._id) },
2301
+ { replace: true }
2302
+ );
2303
+ keys.push(key);
2304
+ }
2305
+ state.mutate(
2306
+ PROPERTIES_ROOT_KEY,
2307
+ { propertyKeys: keys },
2308
+ { replace: true }
2309
+ );
2310
+ };
2311
+ const addProperty = (type, initialData) => {
2312
+ const id = (initialData == null ? void 0 : initialData._id) || generateId();
2313
+ const key = `${index.nodes.Variable}:${id}`;
2314
+ state.mutate({
2315
+ _type: index.nodes.Variable,
2316
+ _id: String(id),
2317
+ type,
2318
+ name: `${type} property`,
2319
+ ...initialData
2320
+ });
2321
+ const root = state.resolve(PROPERTIES_ROOT_KEY);
2322
+ const currentKeys = (root == null ? void 0 : root.propertyKeys) ?? [];
2323
+ state.mutate(
2324
+ PROPERTIES_ROOT_KEY,
2325
+ { propertyKeys: [...currentKeys, key] },
2326
+ { replace: true }
2327
+ );
2328
+ return key;
2329
+ };
2330
+ const removeProperty = (key) => {
2331
+ state.invalidate(key);
2332
+ const root = state.resolve(PROPERTIES_ROOT_KEY);
2333
+ const currentKeys = (root == null ? void 0 : root.propertyKeys) ?? [];
2334
+ state.mutate(
2335
+ PROPERTIES_ROOT_KEY,
2336
+ { propertyKeys: currentKeys.filter((k) => k !== key) },
2337
+ { replace: true }
2338
+ );
2339
+ };
2340
+ const extractProperties = () => {
2341
+ const root = state.resolve(PROPERTIES_ROOT_KEY);
2342
+ const keys = (root == null ? void 0 : root.propertyKeys) ?? [];
2343
+ return keys.map((key) => state.resolve(key, { deep: true })).filter(Boolean);
2344
+ };
2345
+ const getPropertyKeys = () => {
2346
+ const root = state.resolve(PROPERTIES_ROOT_KEY);
2347
+ return (root == null ? void 0 : root.propertyKeys) ?? [];
2348
+ };
2349
+ state.addSkip((dataField) => {
2350
+ if (typeof dataField === "object" && dataField !== null && !Array.isArray(dataField)) {
2351
+ return dataField._type === index.nodes.Variable && (dataField._id === "replaceBeforeSave" || !dataField._id);
2352
+ }
2353
+ return false;
2354
+ });
2355
+ state.mutate({
2356
+ _type: "PropertiesRoot",
2357
+ _id: "root",
2358
+ propertyKeys: []
2359
+ });
2360
+ state.$properties = {
2361
+ key: PROPERTIES_ROOT_KEY,
2362
+ hydrate,
2363
+ addProperty,
2364
+ removeProperty,
2365
+ extractProperties,
2366
+ getPropertyKeys
2367
+ };
2368
+ };
2413
2369
  const fragmentsPlugin = (options) => (state) => {
2414
2370
  const plugins = (options == null ? void 0 : options.plugins) ?? [];
2415
2371
  const createFragmentManager = (fragmentId, initialDocument = {}) => {
@@ -2446,6 +2402,7 @@ const fragmentsPlugin = (options) => (state) => {
2446
2402
  // cssPlugin,
2447
2403
  fragmentStylesheetPlugin(state),
2448
2404
  scopesPlugin,
2405
+ propertiesPlugin,
2449
2406
  ...plugins
2450
2407
  ],
2451
2408
  skip: [
@@ -2456,12 +2413,19 @@ const fragmentsPlugin = (options) => (state) => {
2456
2413
  ...Object.keys(index.nodes),
2457
2414
  "Temp",
2458
2415
  "Spring",
2459
- PLUGIN_TYPES.FragmentStylesheet
2416
+ PLUGIN_TYPES.FragmentStylesheet,
2417
+ "PropertiesRoot"
2460
2418
  ])
2461
2419
  ]
2462
2420
  });
2463
2421
  manager.mutate(tempGraph);
2464
2422
  manager.mutate(springGraph);
2423
+ const fragmentRoot = manager.resolve(manager.$fragment.root);
2424
+ const propertyLinks = (fragmentRoot == null ? void 0 : fragmentRoot.properties) ?? [];
2425
+ const propertyEntities = propertyLinks.map((link) => manager.resolve(link)).filter(Boolean);
2426
+ if (propertyEntities.length > 0) {
2427
+ manager.$properties.hydrate(propertyEntities);
2428
+ }
2465
2429
  state.mutate(state.$fragments.key, {
2466
2430
  managers: {
2467
2431
  [fragmentId]: manager
@@ -2490,9 +2454,6 @@ const fragmentsPlugin = (options) => (state) => {
2490
2454
  });
2491
2455
  return state;
2492
2456
  };
2493
- const addClientMetric = `mutation AddClientMetric($type: ClientMetricType!, $value: GoalAchievementPost!) {
2494
- addClientMetric(metric: {metricType: $type, achievement: $value})
2495
- }`;
2496
2457
  const pendingPixels = /* @__PURE__ */ new Set();
2497
2458
  const sendWithImage = (url) => {
2498
2459
  try {
@@ -2566,10 +2527,16 @@ const types = createConstants(
2566
2527
  "REACH_PROJECT_GOAL"
2567
2528
  );
2568
2529
  const globalMetricsPlugin = (state) => {
2569
- const sendMetric = async (type, value) => {
2530
+ const sendMetric = (type, value) => {
2570
2531
  var _a;
2571
- const query = (_a = state == null ? void 0 : state.$fetch) == null ? void 0 : _a.query;
2572
- await query(addClientMetric, { type, value });
2532
+ if (type !== types.REACH_PROJECT_GOAL || !value) return;
2533
+ const params = new URLSearchParams({
2534
+ goal_id: String(value.goalId),
2535
+ variant_id: String(value.variantId),
2536
+ area_id: String(value.areaId),
2537
+ campaign_id: String(value.campaignId)
2538
+ });
2539
+ (_a = state.$fetch) == null ? void 0 : _a.get(`/api/metric/goal?${params}`).catch(() => void 0);
2573
2540
  };
2574
2541
  const reachGoal = (goal) => {
2575
2542
  sendMetric(types.REACH_PROJECT_GOAL, goal);
@@ -2593,23 +2560,17 @@ const loadPlugin = (state) => {
2593
2560
  const readFragment = (_a = state == null ? void 0 : state.$fetch) == null ? void 0 : _a.readFragment(fragmentId);
2594
2561
  const fragmentManager = (_b = state == null ? void 0 : state.$fragments) == null ? void 0 : _b.getManager(fragmentId);
2595
2562
  if (readFragment && !fragmentManager) {
2596
- const fragmentManager2 = state.$fragments.createFragmentManager(
2597
- fragmentId,
2598
- readFragment
2599
- );
2600
- return fragmentManager2;
2563
+ return state.$fragments.createFragmentManager(fragmentId, readFragment);
2601
2564
  }
2602
2565
  if (readFragment && fragmentManager) return fragmentManager;
2603
- return state.$fetch.queryFragment(fragmentId).then(
2604
- (fragmentDocument) => state.$fragments.createFragmentManager(fragmentId, fragmentDocument)
2605
- );
2566
+ return null;
2606
2567
  };
2607
2568
  const loadArea = (areaCode) => {
2608
2569
  var _a;
2609
2570
  const readArea2 = (_a = state == null ? void 0 : state.$fetch) == null ? void 0 : _a.readArea(areaCode);
2610
2571
  if (readArea2) return readArea2;
2611
- return state.$fetch.queryArea(areaCode).then(async (areaEntity) => {
2612
- await loadFragment(areaEntity == null ? void 0 : areaEntity.fragmentId);
2572
+ return state.$fetch.queryArea(areaCode).then((areaEntity) => {
2573
+ loadFragment(areaEntity == null ? void 0 : areaEntity.fragmentId);
2613
2574
  return areaEntity;
2614
2575
  });
2615
2576
  };
@@ -2626,6 +2587,7 @@ const fontsPlugin = (state) => {
2626
2587
  const fonts = /* @__PURE__ */ new Map();
2627
2588
  let defaultFontFamily = null;
2628
2589
  const registerFont = (font) => {
2590
+ if (!font) return;
2629
2591
  const fontFamily = font.family;
2630
2592
  if (!fonts.has(fontFamily)) {
2631
2593
  fonts.set(fontFamily, font);
@@ -2639,7 +2601,8 @@ const fontsPlugin = (state) => {
2639
2601
  const getStyles = () => {
2640
2602
  const styles = [];
2641
2603
  for (const [fontFamily, font] of fonts) {
2642
- const files = font.files ?? [];
2604
+ const rawFiles = font.files ?? [];
2605
+ const files = Array.isArray(rawFiles) ? rawFiles : Object.entries(rawFiles).map(([variant, url]) => ({ variant, url }));
2643
2606
  for (const file of files) {
2644
2607
  const [weightItem] = getFontWeights([file.variant]);
2645
2608
  styles.push(`@font-face {
@@ -2678,27 +2641,27 @@ const PLUGIN_TYPES = createConstants(
2678
2641
  "FragmentStylesheet"
2679
2642
  );
2680
2643
  const createFragmentsClient = (options) => {
2681
- const BACKEND_TARGET = (options == null ? void 0 : options.isSelf) ? "/graphql" : "http://85.192.29.65/graphql";
2682
2644
  return kt({
2683
2645
  _type: "GlobalManager",
2684
2646
  initialState: {},
2685
2647
  skip: [
2686
2648
  u([
2687
2649
  ...Object.keys(index.nodes),
2688
- ...Object.keys(PLUGIN_TYPES)
2650
+ ...Object.keys(PLUGIN_TYPES),
2651
+ "PropertiesRoot"
2689
2652
  ])
2690
2653
  ],
2691
2654
  plugins: [
2692
2655
  (state) => {
2693
2656
  state.env = {
2694
- isSelf: (options == null ? void 0 : options.isSelf) ?? false,
2695
- backendEndpoint: (options == null ? void 0 : options.backendEndpoint) ?? BACKEND_TARGET,
2657
+ backendEndpoint: (options == null ? void 0 : options.backendEndpoint) ?? "https://client-api.fragmentsx.com",
2696
2658
  apiToken: options == null ? void 0 : options.apiToken,
2697
2659
  referer: options == null ? void 0 : options.referer
2698
2660
  };
2699
2661
  },
2700
2662
  fetchPlugin,
2701
2663
  fontsPlugin,
2664
+ propertiesPlugin,
2702
2665
  fragmentsPlugin({
2703
2666
  plugins: options == null ? void 0 : options.fragmentPlugins
2704
2667
  }),
@@ -2709,6 +2672,39 @@ const createFragmentsClient = (options) => {
2709
2672
  ]
2710
2673
  });
2711
2674
  };
2675
+ const areaMetaPlugin = (options) => (state) => {
2676
+ state.$area = {
2677
+ areaId: options.areaId,
2678
+ campaignId: options.campaignId,
2679
+ variantId: options.variantId
2680
+ };
2681
+ };
2682
+ const createAreaManager = (options) => {
2683
+ var _a;
2684
+ const manager = kt({
2685
+ _type: "AreaManager",
2686
+ _id: String(options.areaId),
2687
+ initialState: {},
2688
+ skip: [
2689
+ u([
2690
+ ...Object.keys(index.nodes),
2691
+ "PropertiesRoot"
2692
+ ])
2693
+ ],
2694
+ plugins: [
2695
+ areaMetaPlugin({
2696
+ areaId: options.areaId,
2697
+ campaignId: options.campaignId,
2698
+ variantId: options.variantId
2699
+ }),
2700
+ propertiesPlugin
2701
+ ]
2702
+ });
2703
+ if ((_a = options.areaProperties) == null ? void 0 : _a.length) {
2704
+ manager.$properties.hydrate(options.areaProperties);
2705
+ }
2706
+ return manager;
2707
+ };
2712
2708
  const ssrPlugin = (state) => {
2713
2709
  var _a, _b, _c;
2714
2710
  if (!["$fragments"].every((field) => field in state)) {
@@ -2769,6 +2765,8 @@ function createTestFragmentsClient(options) {
2769
2765
  }
2770
2766
  return client;
2771
2767
  }
2768
+ exports.createAreaManager = createAreaManager;
2772
2769
  exports.createFragmentsClient = createFragmentsClient;
2773
2770
  exports.createTestFragmentsClient = createTestFragmentsClient;
2771
+ exports.propertiesPlugin = propertiesPlugin;
2774
2772
  exports.ssrPlugin = ssrPlugin;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { createFragmentsClient } from './fragmentsClient';
2
+ export { createAreaManager } from './createAreaManager';
2
3
  export { ssrPlugin } from './plugins/ssr';
4
+ export { propertiesPlugin } from './plugins/properties';
3
5
  export { createTestFragmentsClient, type TestFragmentsClientOptions, type FragmentDocument, type AreaCacheEntity, } from './testing/createTestFragmentsClient';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,qCAAqC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,qCAAqC,CAAC"}