@nubitio/core 0.5.11 → 0.5.14

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.cjs CHANGED
@@ -32,7 +32,8 @@ const _coreConfig = {
32
32
  locale: "es",
33
33
  timezone: "UTC",
34
34
  apiBaseUrl: "/api/",
35
- currency: void 0
35
+ currency: void 0,
36
+ mercureTopicOrigin: void 0
36
37
  };
37
38
  /**
38
39
  * Configure core runtime values (locale, timezone, apiBaseUrl).
@@ -44,6 +45,7 @@ function configureCore(config) {
44
45
  if (config.timezone !== void 0) _coreConfig.timezone = config.timezone;
45
46
  if (config.apiBaseUrl !== void 0) _coreConfig.apiBaseUrl = config.apiBaseUrl;
46
47
  if ("currency" in config) _coreConfig.currency = config.currency;
48
+ if ("mercureTopicOrigin" in config) _coreConfig.mercureTopicOrigin = config.mercureTopicOrigin;
47
49
  }
48
50
  /**
49
51
  * @deprecated Use configureCore() instead.
@@ -62,24 +64,30 @@ function getCoreApiBaseUrl() {
62
64
  function getCoreCurrency() {
63
65
  return _coreConfig.currency;
64
66
  }
67
+ function getMercureTopicOrigin() {
68
+ return _coreConfig.mercureTopicOrigin;
69
+ }
65
70
  const CoreConfigContext = react.default.createContext(_coreConfig);
66
- const CoreConfigProvider = ({ locale, timezone, apiBaseUrl, currency, children }) => {
71
+ const CoreConfigProvider = ({ locale, timezone, apiBaseUrl, currency, mercureTopicOrigin, children }) => {
67
72
  configureCore({
68
73
  locale,
69
74
  timezone,
70
75
  apiBaseUrl,
71
- currency
76
+ currency,
77
+ mercureTopicOrigin
72
78
  });
73
79
  const value = react.default.useMemo(() => ({
74
80
  locale,
75
81
  timezone,
76
82
  apiBaseUrl,
77
- currency
83
+ currency,
84
+ mercureTopicOrigin
78
85
  }), [
79
86
  locale,
80
87
  timezone,
81
88
  apiBaseUrl,
82
- currency
89
+ currency,
90
+ mercureTopicOrigin
83
91
  ]);
84
92
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CoreConfigContext.Provider, {
85
93
  value,
@@ -514,6 +522,230 @@ function initCoreI18n() {
514
522
  i18next.default.addResourceBundle("en", "core", coreTranslationsEn, true, false);
515
523
  }
516
524
  //#endregion
525
+ //#region packages/core/mercure/MercureManager.ts
526
+ var MercureManager = class {
527
+ hubUrl = null;
528
+ topics = /* @__PURE__ */ new Map();
529
+ hubUrlListeners = /* @__PURE__ */ new Set();
530
+ /**
531
+ * Update the hub URL (called by the Axios interceptor when the `Link` header is discovered,
532
+ * or by MercureProvider). Notifies all registered listeners.
533
+ *
534
+ * Idempotent: if the URL is already set to the same value, listeners are NOT re-notified.
535
+ */
536
+ setHubUrl(url) {
537
+ if (this.hubUrl === url) return;
538
+ this.disconnectAll();
539
+ this.hubUrl = url;
540
+ this.hubUrlListeners.forEach((cb) => cb(url));
541
+ }
542
+ getHubUrl() {
543
+ return this.hubUrl;
544
+ }
545
+ /**
546
+ * Register a callback that fires whenever the hub URL changes.
547
+ *
548
+ * Returns an unsubscribe function — call it in a `useEffect` cleanup to avoid memory leaks.
549
+ *
550
+ * @example
551
+ * ```tsx
552
+ * useEffect(() => {
553
+ * return MercureManager.onHubUrlChange(setHubUrl);
554
+ * }, []);
555
+ * ```
556
+ */
557
+ onHubUrlChange(callback) {
558
+ this.hubUrlListeners.add(callback);
559
+ return () => {
560
+ this.hubUrlListeners.delete(callback);
561
+ };
562
+ }
563
+ /**
564
+ * Subscribe to a Mercure topic.
565
+ *
566
+ * @param topic Full topic URI or URI Template, e.g. `https://host/api/products/{id}`.
567
+ * @param callback Called with the parsed JSON payload on each SSE message.
568
+ *
569
+ * If `hubUrl` is null (hub not configured), this is a no-op (graceful degradation).
570
+ * If an EventSource for this topic already exists, it is reused (ref-counting).
571
+ */
572
+ subscribe(topic, callback) {
573
+ if (this.hubUrl === null) return;
574
+ const existing = this.topics.get(topic);
575
+ if (existing) {
576
+ const listener = (e) => {
577
+ try {
578
+ callback(JSON.parse(e.data));
579
+ } catch {
580
+ callback(e.data);
581
+ }
582
+ };
583
+ existing.eventSource.addEventListener("message", listener);
584
+ existing.listeners.set(callback, listener);
585
+ existing.count += 1;
586
+ return;
587
+ }
588
+ const url = new URL(this.hubUrl);
589
+ url.searchParams.append("topic", topic);
590
+ const eventSource = new EventSource(url.toString(), { withCredentials: true });
591
+ const listener = (e) => {
592
+ try {
593
+ callback(JSON.parse(e.data));
594
+ } catch {
595
+ callback(e.data);
596
+ }
597
+ };
598
+ eventSource.addEventListener("message", listener);
599
+ const listeners = /* @__PURE__ */ new Map();
600
+ listeners.set(callback, listener);
601
+ this.topics.set(topic, {
602
+ eventSource,
603
+ count: 1,
604
+ listeners
605
+ });
606
+ }
607
+ /**
608
+ * Unsubscribe a specific callback from a topic.
609
+ *
610
+ * Decrements the ref count. When count reaches 0, the EventSource is closed
611
+ * and removed from the internal map.
612
+ */
613
+ unsubscribe(topic, callback) {
614
+ const entry = this.topics.get(topic);
615
+ if (!entry) return;
616
+ const listener = entry.listeners.get(callback);
617
+ if (listener) {
618
+ entry.eventSource.removeEventListener("message", listener);
619
+ entry.listeners.delete(callback);
620
+ }
621
+ entry.count -= 1;
622
+ if (entry.count <= 0) {
623
+ entry.eventSource.close();
624
+ this.topics.delete(topic);
625
+ }
626
+ }
627
+ /**
628
+ * Close all active EventSource connections and clear the topic map.
629
+ *
630
+ * Called internally when the hub URL changes so stale connections
631
+ * bound to the previous hub are not leaked.
632
+ */
633
+ disconnectAll() {
634
+ this.topics.forEach((entry) => {
635
+ entry.eventSource.close();
636
+ });
637
+ this.topics.clear();
638
+ }
639
+ };
640
+ /** Singleton instance — shared across the entire application. */
641
+ const mercureManager = new MercureManager();
642
+ //#endregion
643
+ //#region packages/core/mercure/mercureDiscovery.ts
644
+ let discoveredTopicOrigin;
645
+ const topicOriginListeners = /* @__PURE__ */ new Set();
646
+ /**
647
+ * Parse a `Link` response header value into `{ url, rel }` pairs.
648
+ * Handles API Platform's `</.well-known/mercure>; rel="mercure"` format.
649
+ */
650
+ function parseLinkHeader(header) {
651
+ const links = [];
652
+ for (const segment of header.split(/,(?=\s*<)/)) {
653
+ const urlMatch = segment.match(/<([^>]+)>/);
654
+ const relMatch = segment.match(/rel=(?:"([^"]+)"|([^;\s,]+))/i);
655
+ if (urlMatch && relMatch) links.push({
656
+ url: urlMatch[1],
657
+ rel: (relMatch[1] ?? relMatch[2]).trim()
658
+ });
659
+ }
660
+ return links;
661
+ }
662
+ /**
663
+ * When the API advertises an absolute hub on another origin (common in Docker:
664
+ * `MERCURE_PUBLIC_URL=http://localhost:3000/...` while the SPA proxies the hub
665
+ * at `/.well-known/mercure`), prefer the same-origin path so EventSource and
666
+ * cookies go through the dev proxy.
667
+ */
668
+ function normalizeMercureHubUrl(hubUrl) {
669
+ if (typeof window === "undefined") return hubUrl;
670
+ try {
671
+ const parsed = new URL(hubUrl, window.location.origin);
672
+ if (parsed.pathname === "/.well-known/mercure" && parsed.origin !== window.location.origin) return `${window.location.origin}${parsed.pathname}`;
673
+ return parsed.toString();
674
+ } catch {
675
+ return hubUrl;
676
+ }
677
+ }
678
+ /**
679
+ * Extract the Mercure hub URL from response headers, if present.
680
+ * Relative URLs are resolved against the request URL.
681
+ */
682
+ function extractMercureHubUrl(headers, responseUrl) {
683
+ const linkHeader = headers.get("link") ?? headers.get("Link");
684
+ if (!linkHeader) return null;
685
+ const mercureLink = parseLinkHeader(linkHeader).find((link) => link.rel === "mercure");
686
+ if (!mercureLink) return null;
687
+ try {
688
+ return normalizeMercureHubUrl(new URL(mercureLink.url, responseUrl).toString());
689
+ } catch {
690
+ return normalizeMercureHubUrl(mercureLink.url);
691
+ }
692
+ }
693
+ function originFromAbsoluteIri(iri) {
694
+ if (!/^https?:\/\//i.test(iri)) return null;
695
+ try {
696
+ return new URL(iri).origin;
697
+ } catch {
698
+ return null;
699
+ }
700
+ }
701
+ /**
702
+ * Infer the API origin from Hydra `@id` values (entrypoint or collection items).
703
+ * API Platform publishes absolute IRIs when `DEFAULT_URI` is configured.
704
+ */
705
+ function extractTopicOriginFromPayload(data) {
706
+ if (!data || typeof data !== "object") return null;
707
+ const record = data;
708
+ if (typeof record["@id"] === "string") {
709
+ const origin = originFromAbsoluteIri(record["@id"]);
710
+ if (origin) return origin;
711
+ }
712
+ const members = record["hydra:member"];
713
+ if (Array.isArray(members)) for (const member of members) {
714
+ if (!member || typeof member !== "object") continue;
715
+ const memberId = member["@id"];
716
+ if (typeof memberId === "string") {
717
+ const origin = originFromAbsoluteIri(memberId);
718
+ if (origin) return origin;
719
+ }
720
+ }
721
+ return null;
722
+ }
723
+ function getDiscoveredMercureTopicOrigin() {
724
+ return discoveredTopicOrigin;
725
+ }
726
+ /** Subscribe to autodiscovered topic-origin changes (for React hooks). */
727
+ function onMercureTopicOriginChange(callback) {
728
+ topicOriginListeners.add(callback);
729
+ return () => {
730
+ topicOriginListeners.delete(callback);
731
+ };
732
+ }
733
+ function setDiscoveredTopicOrigin(origin) {
734
+ if (discoveredTopicOrigin === origin) return;
735
+ discoveredTopicOrigin = origin;
736
+ topicOriginListeners.forEach((listener) => listener(origin));
737
+ }
738
+ /**
739
+ * Inspect an API response and update Mercure hub URL / topic origin when found.
740
+ * Called from `CoreHttpClient` on every successful response.
741
+ */
742
+ function discoverMercureFromResponse(response, data) {
743
+ const hubUrl = extractMercureHubUrl(response.headers, response.url);
744
+ if (hubUrl) mercureManager.setHubUrl(hubUrl);
745
+ const topicOrigin = extractTopicOriginFromPayload(data);
746
+ if (topicOrigin) setDiscoveredTopicOrigin(topicOrigin);
747
+ }
748
+ //#endregion
517
749
  //#region packages/core/http/CoreHttpClient.ts
518
750
  function joinUrl(baseUrl, url) {
519
751
  if (/^https?:\/\//.test(url) || url.startsWith("/")) return url;
@@ -609,12 +841,16 @@ var CoreHttpClient = class {
609
841
  signal: config?.signal,
610
842
  body: body === void 0 || body === null ? void 0 : body instanceof FormData ? body : JSON.stringify(body)
611
843
  });
612
- if (response.ok) return {
613
- response,
614
- data: await readResponseBody(response, config?.responseType),
615
- headers: response.headers,
616
- status: response.status
617
- };
844
+ if (response.ok) {
845
+ const data = await readResponseBody(response, config?.responseType);
846
+ if (config?.responseType === void 0 || config.responseType === "json") discoverMercureFromResponse(response, data);
847
+ return {
848
+ response,
849
+ data,
850
+ headers: response.headers,
851
+ status: response.status
852
+ };
853
+ }
618
854
  const errorData = await this.safeErrorData(response);
619
855
  const error = createHttpError(errorData.detail ?? errorData.message ?? "HTTP request failed", response.status, errorData);
620
856
  const loginPath = this.config.loginPath ?? "auth/login";
@@ -713,124 +949,6 @@ function CoreProvider({ children, http, httpClient, runtime }) {
713
949
  });
714
950
  }
715
951
  //#endregion
716
- //#region packages/core/mercure/MercureManager.ts
717
- var MercureManager = class {
718
- hubUrl = null;
719
- topics = /* @__PURE__ */ new Map();
720
- hubUrlListeners = /* @__PURE__ */ new Set();
721
- /**
722
- * Update the hub URL (called by the Axios interceptor when the `Link` header is discovered,
723
- * or by MercureProvider). Notifies all registered listeners.
724
- *
725
- * Idempotent: if the URL is already set to the same value, listeners are NOT re-notified.
726
- */
727
- setHubUrl(url) {
728
- if (this.hubUrl === url) return;
729
- this.disconnectAll();
730
- this.hubUrl = url;
731
- this.hubUrlListeners.forEach((cb) => cb(url));
732
- }
733
- getHubUrl() {
734
- return this.hubUrl;
735
- }
736
- /**
737
- * Register a callback that fires whenever the hub URL changes.
738
- *
739
- * Returns an unsubscribe function — call it in a `useEffect` cleanup to avoid memory leaks.
740
- *
741
- * @example
742
- * ```tsx
743
- * useEffect(() => {
744
- * return MercureManager.onHubUrlChange(setHubUrl);
745
- * }, []);
746
- * ```
747
- */
748
- onHubUrlChange(callback) {
749
- this.hubUrlListeners.add(callback);
750
- return () => {
751
- this.hubUrlListeners.delete(callback);
752
- };
753
- }
754
- /**
755
- * Subscribe to a Mercure topic.
756
- *
757
- * @param topic Full topic URI or URI Template, e.g. `https://host/api/products/{id}`.
758
- * @param callback Called with the parsed JSON payload on each SSE message.
759
- *
760
- * If `hubUrl` is null (hub not configured), this is a no-op (graceful degradation).
761
- * If an EventSource for this topic already exists, it is reused (ref-counting).
762
- */
763
- subscribe(topic, callback) {
764
- if (this.hubUrl === null) return;
765
- const existing = this.topics.get(topic);
766
- if (existing) {
767
- const listener = (e) => {
768
- try {
769
- callback(JSON.parse(e.data));
770
- } catch {
771
- callback(e.data);
772
- }
773
- };
774
- existing.eventSource.addEventListener("message", listener);
775
- existing.listeners.set(callback, listener);
776
- existing.count += 1;
777
- return;
778
- }
779
- const url = new URL(this.hubUrl);
780
- url.searchParams.append("topic", topic);
781
- const eventSource = new EventSource(url.toString(), { withCredentials: true });
782
- const listener = (e) => {
783
- try {
784
- callback(JSON.parse(e.data));
785
- } catch {
786
- callback(e.data);
787
- }
788
- };
789
- eventSource.addEventListener("message", listener);
790
- const listeners = /* @__PURE__ */ new Map();
791
- listeners.set(callback, listener);
792
- this.topics.set(topic, {
793
- eventSource,
794
- count: 1,
795
- listeners
796
- });
797
- }
798
- /**
799
- * Unsubscribe a specific callback from a topic.
800
- *
801
- * Decrements the ref count. When count reaches 0, the EventSource is closed
802
- * and removed from the internal map.
803
- */
804
- unsubscribe(topic, callback) {
805
- const entry = this.topics.get(topic);
806
- if (!entry) return;
807
- const listener = entry.listeners.get(callback);
808
- if (listener) {
809
- entry.eventSource.removeEventListener("message", listener);
810
- entry.listeners.delete(callback);
811
- }
812
- entry.count -= 1;
813
- if (entry.count <= 0) {
814
- entry.eventSource.close();
815
- this.topics.delete(topic);
816
- }
817
- }
818
- /**
819
- * Close all active EventSource connections and clear the topic map.
820
- *
821
- * Called internally when the hub URL changes so stale connections
822
- * bound to the previous hub are not leaked.
823
- */
824
- disconnectAll() {
825
- this.topics.forEach((entry) => {
826
- entry.eventSource.close();
827
- });
828
- this.topics.clear();
829
- }
830
- };
831
- /** Singleton instance — shared across the entire application. */
832
- const mercureManager = new MercureManager();
833
- //#endregion
834
952
  //#region packages/core/mercure/MercureProvider.tsx
835
953
  /**
836
954
  * MercureProvider — React context provider for the Mercure hub URL.
@@ -843,14 +961,19 @@ const mercureManager = new MercureManager();
843
961
  * ## Usage
844
962
  *
845
963
  * ```tsx
846
- * // In your app root:
847
- * <MercureProvider hubUrl={discoveredHubUrl}>
964
+ * // Autodiscovery (recommended): hub URL comes from API `Link` headers.
965
+ * <MercureProvider>
966
+ * <App />
967
+ * </MercureProvider>
968
+ *
969
+ * // Manual override (e.g. before the first API response):
970
+ * <MercureProvider hubUrl="/.well-known/mercure">
848
971
  * <App />
849
972
  * </MercureProvider>
850
973
  * ```
851
974
  *
852
- * The `hubUrl` is typically discovered from the `Link` header of API responses
853
- * (common pattern with API Platform + Mercure).
975
+ * The hub URL is autodiscovered from the `Link` header of API responses
976
+ * (API Platform + Mercure). Pass `hubUrl` only when you need an explicit override.
854
977
  */
855
978
  /** The hub URL, or null if Mercure is not configured / not yet discovered. */
856
979
  const MercureContext = (0, react.createContext)(null);
@@ -858,10 +981,17 @@ const MercureContext = (0, react.createContext)(null);
858
981
  * Provides the Mercure hub URL to the React tree and keeps `MercureManager`
859
982
  * in sync whenever the URL changes.
860
983
  */
861
- function MercureProvider({ hubUrl, children }) {
984
+ function MercureProvider({ hubUrl: hubUrlOverride, children }) {
985
+ const [discoveredHubUrl, setDiscoveredHubUrl] = (0, react.useState)(() => mercureManager.getHubUrl());
862
986
  (0, react.useEffect)(() => {
863
- mercureManager.setHubUrl(hubUrl);
864
- }, [hubUrl]);
987
+ if (hubUrlOverride !== void 0) {
988
+ mercureManager.setHubUrl(hubUrlOverride);
989
+ return;
990
+ }
991
+ setDiscoveredHubUrl(mercureManager.getHubUrl());
992
+ return mercureManager.onHubUrlChange(setDiscoveredHubUrl);
993
+ }, [hubUrlOverride]);
994
+ const hubUrl = hubUrlOverride !== void 0 ? hubUrlOverride : discoveredHubUrl;
865
995
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MercureContext.Provider, {
866
996
  value: hubUrl,
867
997
  children
@@ -878,7 +1008,8 @@ function MercureProvider({ hubUrl, children }) {
878
1008
  * - Mercure is not configured in the backend.
879
1009
  *
880
1010
  * This hook does NOT perform any fetch or side effect — it only reads from context.
881
- * Hub discovery (usually from a `Link` header) must be done by the host application.
1011
+ * Hub discovery happens automatically via `CoreHttpClient` (`Link` header parsing).
1012
+ * Use `<MercureProvider>` without a `hubUrl` prop to expose the discovered URL.
882
1013
  *
883
1014
  * ## Usage
884
1015
  *
@@ -895,6 +1026,52 @@ function useMercureHub() {
895
1026
  return (0, react.useContext)(MercureContext);
896
1027
  }
897
1028
  //#endregion
1029
+ //#region packages/core/mercure/mercureTopics.ts
1030
+ /**
1031
+ * Resolves the origin used to build Mercure collection topic URIs.
1032
+ *
1033
+ * API Platform publishes item updates to IRIs such as
1034
+ * `http://localhost:8000/api/products/42`. The SPA may run on another origin
1035
+ * in dev (Vite on :5173, API on :8000). The origin is normally autodiscovered
1036
+ * from absolute Hydra `@id` values on API responses. Set `mercureTopicOrigin`
1037
+ * on CoreConfig only when autodiscovery cannot infer the correct origin.
1038
+ */
1039
+ function resolveMercureTopicOrigin(apiBaseUrl = getCoreApiBaseUrl(), configuredOrigin, discoveredOrigin = getDiscoveredMercureTopicOrigin()) {
1040
+ const explicit = configuredOrigin?.trim().replace(/\/+$/, "");
1041
+ if (explicit) return explicit;
1042
+ const discovered = discoveredOrigin?.trim().replace(/\/+$/, "");
1043
+ if (discovered) return discovered;
1044
+ const trimmedBase = apiBaseUrl.trim();
1045
+ if (/^https?:\/\//i.test(trimmedBase)) try {
1046
+ return new URL(trimmedBase).origin;
1047
+ } catch {}
1048
+ if (typeof window !== "undefined") return window.location.origin;
1049
+ return "";
1050
+ }
1051
+ /**
1052
+ * Wildcard collection topic (RFC 6570 URI Template) for a resource API path.
1053
+ * e.g. `/api/products` → `http://localhost:8000/api/products/{id}`
1054
+ */
1055
+ function buildMercureCollectionTopic(apiUrl, configuredOrigin, apiBaseUrl = getCoreApiBaseUrl()) {
1056
+ if (!apiUrl) return null;
1057
+ const origin = resolveMercureTopicOrigin(apiBaseUrl, configuredOrigin);
1058
+ if (!origin) return null;
1059
+ const normalizedPath = apiUrl.replace(/^\//, "").replace(/\/+$/, "");
1060
+ if (!normalizedPath) return null;
1061
+ return `${origin}/${normalizedPath}/{id}`;
1062
+ }
1063
+ //#endregion
1064
+ //#region packages/core/mercure/useDiscoveredMercureTopicOrigin.ts
1065
+ /**
1066
+ * Returns the Mercure topic origin autodiscovered from Hydra `@id` IRIs.
1067
+ * Re-renders when a new origin is discovered from a subsequent API response.
1068
+ */
1069
+ function useDiscoveredMercureTopicOrigin() {
1070
+ const [origin, setOrigin] = (0, react.useState)(getDiscoveredMercureTopicOrigin);
1071
+ (0, react.useEffect)(() => onMercureTopicOriginChange(setOrigin), []);
1072
+ return origin;
1073
+ }
1074
+ //#endregion
898
1075
  //#region packages/core/mercure/useMercureSubscription.ts
899
1076
  /**
900
1077
  * useMercureSubscription — Hook that subscribes to a Mercure topic and calls
@@ -904,6 +1081,9 @@ function useMercureHub() {
904
1081
  * - If `hubUrl` is null (Mercure not configured) or `enabled` is false → no-op.
905
1082
  * - Subscribes to the wildcard topic `<origin>/<apiUrl>/{id}` (URI Template RFC 6570),
906
1083
  * which captures any item-level event (create / update / delete) for the collection.
1084
+ * - `<origin>` comes from `CoreConfig.mercureTopicOrigin`, autodiscovered Hydra
1085
+ * `@id`, an absolute `apiBaseUrl`, or `window.location.origin`
1086
+ * (see `buildMercureCollectionTopic`).
907
1087
  * - Cleanup: unsubscribes on unmount or when dependencies change (no memory leaks).
908
1088
  *
909
1089
  * ## Usage
@@ -923,10 +1103,12 @@ function useMercureHub() {
923
1103
  */
924
1104
  function useMercureSubscription(apiUrl, onUpdate, enabled = true) {
925
1105
  const hubUrl = useMercureHub();
1106
+ const { mercureTopicOrigin, apiBaseUrl } = useCoreConfig();
1107
+ const discoveredTopicOrigin = useDiscoveredMercureTopicOrigin();
926
1108
  (0, react.useEffect)(() => {
927
1109
  if (!hubUrl || !enabled || !apiUrl) return;
928
- const normalizedPath = apiUrl.replace(/^\//, "");
929
- const topic = `${window.location.origin}/${normalizedPath}/{id}`;
1110
+ const topic = buildMercureCollectionTopic(apiUrl, mercureTopicOrigin ?? discoveredTopicOrigin, apiBaseUrl);
1111
+ if (!topic) return;
930
1112
  const handler = (_data) => {
931
1113
  onUpdate();
932
1114
  };
@@ -937,7 +1119,10 @@ function useMercureSubscription(apiUrl, onUpdate, enabled = true) {
937
1119
  }, [
938
1120
  hubUrl,
939
1121
  enabled,
940
- apiUrl
1122
+ apiUrl,
1123
+ mercureTopicOrigin,
1124
+ discoveredTopicOrigin,
1125
+ apiBaseUrl
941
1126
  ]);
942
1127
  }
943
1128
  //#endregion
@@ -950,6 +1135,7 @@ exports.DEFAULT_TIMEZONE = DEFAULT_TIMEZONE;
950
1135
  exports.DateUtils = DateUtils;
951
1136
  exports.MercureManager = mercureManager;
952
1137
  exports.MercureProvider = MercureProvider;
1138
+ exports.buildMercureCollectionTopic = buildMercureCollectionTopic;
953
1139
  exports.configureCore = configureCore;
954
1140
  exports.configureCoreDate = configureCoreDate;
955
1141
  exports.coreTranslationsEn = coreTranslationsEn;
@@ -957,16 +1143,24 @@ exports.coreTranslationsEs = coreTranslationsEs;
957
1143
  exports.createCoreHttpClient = createCoreHttpClient;
958
1144
  exports.createCrudEvents = createCrudEvents;
959
1145
  exports.createScopedEventBus = createScopedEventBus;
1146
+ exports.discoverMercureFromResponse = discoverMercureFromResponse;
960
1147
  exports.dispatch = dispatch;
1148
+ exports.extractMercureHubUrl = extractMercureHubUrl;
1149
+ exports.extractTopicOriginFromPayload = extractTopicOriginFromPayload;
961
1150
  exports.getCoreApiBaseUrl = getCoreApiBaseUrl;
962
1151
  exports.getCoreCurrency = getCoreCurrency;
963
1152
  exports.getCoreLocale = getCoreLocale;
964
1153
  exports.getCoreTimezone = getCoreTimezone;
1154
+ exports.getDiscoveredMercureTopicOrigin = getDiscoveredMercureTopicOrigin;
1155
+ exports.getMercureTopicOrigin = getMercureTopicOrigin;
965
1156
  exports.initCoreI18n = initCoreI18n;
1157
+ exports.parseLinkHeader = parseLinkHeader;
1158
+ exports.resolveMercureTopicOrigin = resolveMercureTopicOrigin;
966
1159
  exports.useCoreConfig = useCoreConfig;
967
1160
  exports.useCoreHttpClient = useCoreHttpClient;
968
1161
  exports.useCoreRuntime = useCoreRuntime;
969
1162
  exports.useCoreTranslation = useCoreTranslation;
1163
+ exports.useDiscoveredMercureTopicOrigin = useDiscoveredMercureTopicOrigin;
970
1164
  exports.useEvents = useEvents;
971
1165
  exports.useMercureHub = useMercureHub;
972
1166
  exports.useMercureSubscription = useMercureSubscription;