@axcode/axcloud-sdk 0.1.7-dev.87ea138 → 0.1.7-dev.bf490b9

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 CHANGED
@@ -30,19 +30,9 @@ var AxCloudError = class _AxCloudError extends Error {
30
30
  details
31
31
  );
32
32
  case 403:
33
- return new _AxCloudError(
34
- message || "Access denied",
35
- "FORBIDDEN",
36
- status,
37
- details
38
- );
33
+ return new _AxCloudError(message || "Access denied", "FORBIDDEN", status, details);
39
34
  case 404:
40
- return new _AxCloudError(
41
- message || "Resource not found",
42
- "NOT_FOUND",
43
- status,
44
- details
45
- );
35
+ return new _AxCloudError(message || "Resource not found", "NOT_FOUND", status, details);
46
36
  case 422:
47
37
  return new _AxCloudError(
48
38
  message || "Validation failed",
@@ -52,19 +42,9 @@ var AxCloudError = class _AxCloudError extends Error {
52
42
  );
53
43
  default:
54
44
  if (status >= 500) {
55
- return new _AxCloudError(
56
- message || "Server error",
57
- "SERVER_ERROR",
58
- status,
59
- details
60
- );
45
+ return new _AxCloudError(message || "Server error", "SERVER_ERROR", status, details);
61
46
  }
62
- return new _AxCloudError(
63
- message || "An error occurred",
64
- "UNKNOWN_ERROR",
65
- status,
66
- details
67
- );
47
+ return new _AxCloudError(message || "An error occurred", "UNKNOWN_ERROR", status, details);
68
48
  }
69
49
  }
70
50
  static networkError(originalError) {
@@ -78,12 +58,9 @@ var AxCloudError = class _AxCloudError extends Error {
78
58
  );
79
59
  }
80
60
  static timeoutError(timeoutMs) {
81
- return new _AxCloudError(
82
- `Request timed out after ${timeoutMs}ms`,
83
- "TIMEOUT_ERROR",
84
- 0,
85
- { timeout: timeoutMs }
86
- );
61
+ return new _AxCloudError(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", 0, {
62
+ timeout: timeoutMs
63
+ });
87
64
  }
88
65
  };
89
66
  function isAxCloudError(error) {
@@ -238,6 +215,130 @@ function getClient(key) {
238
215
  throw new Error("AxCloud client not found. Make sure AxCloudProvider is mounted and use useAxCloudContext() to get the client.");
239
216
  }
240
217
 
218
+ // src/core/analytics.ts
219
+ var EVENT_NAME_PATTERN = /^[a-z][a-z0-9_]{1,63}$/;
220
+ var PROPERTY_KEY_PATTERN = /^[a-z][a-z0-9_]{0,47}$/;
221
+ var SENSITIVE_PROPERTY_PATTERN = /(^|_)(auth0|email|name|password|query|search|secret|token|trace|user|userid)($|_)/;
222
+ var EMAIL_VALUE_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
223
+ var OPAQUE_SEGMENT_PATTERNS = [
224
+ /^[0-9a-f]{8}-[0-9a-f-]{27,}$/i,
225
+ /^(org|user|section|document|content|poll|invitation|invite|trace|chan)[_-][a-z0-9_-]+$/i,
226
+ /^[a-f0-9]{20,}$/i,
227
+ /^[a-z0-9_-]{32,}$/i
228
+ ];
229
+ var scriptLoads = /* @__PURE__ */ new Map();
230
+ function isLocalAnalyticsHostname(hostname) {
231
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
232
+ }
233
+ function sanitizeAnalyticsPath(pathname, customNormalizer) {
234
+ const rawPath = pathname.split(/[?#]/, 1)[0] || "/";
235
+ const normalizedInput = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
236
+ const custom = customNormalizer?.(normalizedInput);
237
+ if (custom === null) return null;
238
+ const path = custom ?? normalizedInput;
239
+ const cleanPath = path.split(/[?#]/, 1)[0] || "/";
240
+ const segments = cleanPath.split("/").map((segment) => {
241
+ if (!segment) return segment;
242
+ let decoded = segment;
243
+ try {
244
+ decoded = decodeURIComponent(segment);
245
+ } catch {
246
+ }
247
+ return OPAQUE_SEGMENT_PATTERNS.some((pattern) => pattern.test(decoded)) ? ":id" : segment;
248
+ });
249
+ return segments.join("/") || "/";
250
+ }
251
+ function sanitizeAnalyticsEventData(data) {
252
+ if (!data) return void 0;
253
+ const sanitized = {};
254
+ for (const [rawKey, rawValue] of Object.entries(data).slice(0, 20)) {
255
+ const key = rawKey.trim().toLowerCase();
256
+ if (!PROPERTY_KEY_PATTERN.test(key) || SENSITIVE_PROPERTY_PATTERN.test(key)) continue;
257
+ if (typeof rawValue === "string") {
258
+ const value = rawValue.trim();
259
+ if (!value || value.length > 100 || EMAIL_VALUE_PATTERN.test(value)) continue;
260
+ sanitized[key] = value;
261
+ continue;
262
+ }
263
+ if (typeof rawValue === "number" && Number.isFinite(rawValue)) {
264
+ sanitized[key] = rawValue;
265
+ continue;
266
+ }
267
+ if (typeof rawValue === "boolean") sanitized[key] = rawValue;
268
+ }
269
+ return Object.keys(sanitized).length > 0 ? sanitized : void 0;
270
+ }
271
+ function isAllowedAnalyticsEvent(eventName, allowedEvents) {
272
+ return EVENT_NAME_PATTERN.test(eventName) && Boolean(allowedEvents?.includes(eventName));
273
+ }
274
+ async function fetchAnalyticsPublicConfig(input) {
275
+ const baseUrl = input.apiUrl.replace(/\/$/, "");
276
+ const url = new URL(`${baseUrl}/analytics/public/config`);
277
+ url.searchParams.set("orgId", input.orgId);
278
+ url.searchParams.set("siteKey", input.siteKey);
279
+ url.searchParams.set("stage", input.stage);
280
+ url.searchParams.set("hostname", input.hostname);
281
+ const response = await fetch(url, {
282
+ method: "GET",
283
+ headers: { Accept: "application/json" },
284
+ signal: input.signal
285
+ });
286
+ if (!response.ok) throw new Error(`Analytics configuration returned ${response.status}`);
287
+ return response.json();
288
+ }
289
+ function loadAnalyticsScript(config, doc = document) {
290
+ if (!config.enabled || !config.websiteId || !config.scriptUrl) {
291
+ return Promise.reject(new Error("Analytics tracker configuration is incomplete"));
292
+ }
293
+ const key = `${config.scriptUrl}|${config.websiteId}`;
294
+ const existingPromise = scriptLoads.get(key);
295
+ if (existingPromise) return existingPromise;
296
+ const existing = doc.querySelector(
297
+ `script[data-axcloud-analytics-site="${config.websiteId}"]`
298
+ );
299
+ if (existing && doc.defaultView?.umami) {
300
+ return Promise.resolve();
301
+ }
302
+ const promise = new Promise((resolve, reject) => {
303
+ const script = existing || doc.createElement("script");
304
+ const onLoad = () => resolve();
305
+ const onError = () => reject(new Error("Analytics tracker failed to load"));
306
+ script.addEventListener("load", onLoad, { once: true });
307
+ script.addEventListener("error", onError, { once: true });
308
+ if (!existing) {
309
+ script.src = config.scriptUrl;
310
+ script.defer = true;
311
+ script.dataset.websiteId = config.websiteId;
312
+ script.dataset.axcloudAnalyticsSite = config.websiteId;
313
+ script.dataset.autoTrack = String(config.autoTrack === true);
314
+ if (config.hostUrl) script.dataset.hostUrl = config.hostUrl;
315
+ if (config.domains?.length) script.dataset.domains = config.domains.join(",");
316
+ if (config.respectDoNotTrack !== false) script.dataset.doNotTrack = "true";
317
+ if (config.excludeSearch !== false) script.dataset.excludeSearch = "true";
318
+ if (config.excludeHash !== false) script.dataset.excludeHash = "true";
319
+ doc.head.appendChild(script);
320
+ }
321
+ }).catch((error) => {
322
+ scriptLoads.delete(key);
323
+ throw error;
324
+ });
325
+ scriptLoads.set(key, promise);
326
+ return promise;
327
+ }
328
+ function sendAnalyticsPageView(pathname, options, targetWindow = window) {
329
+ const path = sanitizeAnalyticsPath(pathname, options.normalizePath);
330
+ const umami = targetWindow.umami;
331
+ if (!path || !umami) return false;
332
+ umami.track({ url: path, title: targetWindow.document.title });
333
+ return true;
334
+ }
335
+ function sendAnalyticsEvent(eventName, data, allowedEvents, targetWindow = window) {
336
+ const umami = targetWindow.umami;
337
+ if (!umami || !isAllowedAnalyticsEvent(eventName, allowedEvents)) return false;
338
+ umami.track(eventName, sanitizeAnalyticsEventData(data));
339
+ return true;
340
+ }
341
+
241
342
  // src/core/contentSlots.ts
242
343
  var SLOT_ATTRIBUTE_KEYS = ["slot", "field", "key", "name"];
243
344
  function getContentSlotMap(content) {
@@ -533,6 +634,127 @@ function useAxCloudContext() {
533
634
  }
534
635
  return context;
535
636
  }
637
+ var NAVIGATION_EVENT = "axcloud-sdk:navigation";
638
+ var historySubscriberCount = 0;
639
+ var originalPushState = null;
640
+ var originalReplaceState = null;
641
+ function subscribeToNavigation(callback) {
642
+ if (typeof window === "undefined") return () => void 0;
643
+ if (historySubscriberCount === 0) {
644
+ originalPushState = window.history.pushState.bind(window.history);
645
+ originalReplaceState = window.history.replaceState.bind(window.history);
646
+ window.history.pushState = ((...args) => {
647
+ originalPushState?.(...args);
648
+ window.dispatchEvent(new Event(NAVIGATION_EVENT));
649
+ });
650
+ window.history.replaceState = ((...args) => {
651
+ originalReplaceState?.(...args);
652
+ window.dispatchEvent(new Event(NAVIGATION_EVENT));
653
+ });
654
+ }
655
+ historySubscriberCount += 1;
656
+ window.addEventListener("popstate", callback);
657
+ window.addEventListener(NAVIGATION_EVENT, callback);
658
+ return () => {
659
+ window.removeEventListener("popstate", callback);
660
+ window.removeEventListener(NAVIGATION_EVENT, callback);
661
+ historySubscriberCount = Math.max(0, historySubscriberCount - 1);
662
+ if (historySubscriberCount === 0) {
663
+ if (originalPushState) window.history.pushState = originalPushState;
664
+ if (originalReplaceState) window.history.replaceState = originalReplaceState;
665
+ originalPushState = null;
666
+ originalReplaceState = null;
667
+ }
668
+ };
669
+ }
670
+ function doNotTrackEnabled(config) {
671
+ if (config.respectDoNotTrack === false || typeof navigator === "undefined") return false;
672
+ return navigator.doNotTrack === "1";
673
+ }
674
+ function useAnalyticsRuntime(config) {
675
+ const [enabled, setEnabled] = react.useState(false);
676
+ const [ready, setReady] = react.useState(false);
677
+ const publicConfigRef = react.useRef(null);
678
+ const optionsRef = react.useRef(config.analytics);
679
+ optionsRef.current = config.analytics;
680
+ const trackPageView = react.useCallback(
681
+ (pathname) => {
682
+ if (!ready || !optionsRef.current || typeof window === "undefined") return false;
683
+ return sendAnalyticsPageView(pathname || window.location.pathname, optionsRef.current);
684
+ },
685
+ [ready]
686
+ );
687
+ const track = react.useCallback(
688
+ (eventName, data) => {
689
+ if (!ready || typeof window === "undefined") return false;
690
+ return sendAnalyticsEvent(eventName, data, publicConfigRef.current?.allowedEvents);
691
+ },
692
+ [ready]
693
+ );
694
+ react.useEffect(() => {
695
+ const options = config.analytics;
696
+ setEnabled(false);
697
+ setReady(false);
698
+ publicConfigRef.current = null;
699
+ if (!options?.enabled || !options.siteKey || typeof window === "undefined") return void 0;
700
+ if (isLocalAnalyticsHostname(window.location.hostname) && !options.trackLocalhost)
701
+ return void 0;
702
+ const controller = new AbortController();
703
+ let cancelled = false;
704
+ let unsubscribe = () => void 0;
705
+ const initialize = async () => {
706
+ try {
707
+ const publicConfig = await fetchAnalyticsPublicConfig({
708
+ apiUrl: config.apiUrl,
709
+ orgId: config.orgId,
710
+ siteKey: options.siteKey,
711
+ stage: config.stage,
712
+ hostname: window.location.hostname,
713
+ signal: controller.signal
714
+ });
715
+ if (cancelled || !publicConfig.enabled || doNotTrackEnabled(publicConfig)) return;
716
+ publicConfigRef.current = publicConfig;
717
+ setEnabled(true);
718
+ await loadAnalyticsScript(publicConfig);
719
+ if (cancelled) return;
720
+ setReady(true);
721
+ if (!publicConfig.autoTrack) {
722
+ const trackCurrentPage = () => {
723
+ sendAnalyticsPageView(window.location.pathname, options);
724
+ };
725
+ trackCurrentPage();
726
+ unsubscribe = subscribeToNavigation(trackCurrentPage);
727
+ }
728
+ } catch (error) {
729
+ if (!cancelled && !(error instanceof Error && error.name === "AbortError")) {
730
+ setEnabled(false);
731
+ setReady(false);
732
+ }
733
+ }
734
+ };
735
+ void initialize();
736
+ return () => {
737
+ cancelled = true;
738
+ controller.abort();
739
+ unsubscribe();
740
+ };
741
+ }, [
742
+ config.analytics?.enabled,
743
+ config.analytics?.siteKey,
744
+ config.analytics?.trackLocalhost,
745
+ config.analytics?.normalizePath,
746
+ config.apiUrl,
747
+ config.orgId,
748
+ config.stage
749
+ ]);
750
+ return react.useMemo(
751
+ () => ({ enabled, ready, track, trackPageView }),
752
+ [enabled, ready, track, trackPageView]
753
+ );
754
+ }
755
+ function useAnalytics() {
756
+ return useAxCloudContext().analytics;
757
+ }
536
758
  var defaultQueryClient = new reactQuery.QueryClient({
537
759
  defaultOptions: {
538
760
  queries: {
@@ -551,6 +773,7 @@ function AxCloudInnerProvider({
551
773
  timeout
552
774
  }) {
553
775
  const { getAccessTokenSilently, isAuthenticated } = auth0React.useAuth0();
776
+ const analytics = useAnalyticsRuntime(config);
554
777
  const tokenGetterRef = react.useRef(async () => void 0);
555
778
  tokenGetterRef.current = isAuthenticated ? async () => {
556
779
  try {
@@ -580,9 +803,10 @@ function AxCloudInnerProvider({
580
803
  client,
581
804
  orgId: config.orgId,
582
805
  stage: config.stage,
583
- isPublicMode: Boolean(config.apiKey) && !isAuthenticated
806
+ isPublicMode: Boolean(config.apiKey) && !isAuthenticated,
807
+ analytics
584
808
  }),
585
- [config, client, isAuthenticated]
809
+ [config, client, isAuthenticated, analytics]
586
810
  );
587
811
  return /* @__PURE__ */ jsxRuntime.jsx(AxCloudContext.Provider, { value: contextValue, children });
588
812
  }
@@ -592,6 +816,7 @@ function AxCloudProvider({
592
816
  apiUrl,
593
817
  stage = "dev",
594
818
  apiKey,
819
+ analytics,
595
820
  auth0,
596
821
  queryClient = defaultQueryClient,
597
822
  timeout
@@ -602,9 +827,10 @@ function AxCloudProvider({
602
827
  apiUrl,
603
828
  stage,
604
829
  apiKey,
830
+ analytics,
605
831
  auth0
606
832
  }),
607
- [orgId, apiUrl, stage, apiKey, auth0]
833
+ [orgId, apiUrl, stage, apiKey, analytics, auth0]
608
834
  );
609
835
  return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(
610
836
  auth0React.Auth0Provider,
@@ -613,14 +839,15 @@ function AxCloudProvider({
613
839
  clientId: auth0.clientId,
614
840
  authorizationParams: {
615
841
  redirect_uri: auth0.redirectUri,
616
- audience: auth0.audience
842
+ audience: auth0.audience,
843
+ ...auth0.organization ? { organization: auth0.organization } : {}
617
844
  },
618
845
  children: /* @__PURE__ */ jsxRuntime.jsx(AxCloudInnerProvider, { config, timeout, children })
619
846
  }
620
847
  ) });
621
848
  }
622
849
  function useAuth() {
623
- const { config } = useAxCloudContext();
850
+ const { config, client } = useAxCloudContext();
624
851
  const {
625
852
  isAuthenticated,
626
853
  isLoading,
@@ -636,10 +863,15 @@ function useAuth() {
636
863
  return loginWithRedirect({
637
864
  appState: {
638
865
  returnTo: options?.returnTo || window.location.pathname
639
- }
866
+ },
867
+ ...config.auth0.organization ? {
868
+ authorizationParams: {
869
+ organization: config.auth0.organization
870
+ }
871
+ } : {}
640
872
  });
641
873
  },
642
- [loginWithRedirect]
874
+ [config.auth0.organization, loginWithRedirect]
643
875
  );
644
876
  const logout = react.useCallback(
645
877
  (options) => {
@@ -658,6 +890,60 @@ function useAuth() {
658
890
  return void 0;
659
891
  }
660
892
  }, [getAccessTokenSilently]);
893
+ const refreshUser = react.useCallback(async () => {
894
+ await getAccessTokenSilently({ cacheMode: "off" });
895
+ const claims = await getIdTokenClaims();
896
+ return claims?.email_verified === true;
897
+ }, [getAccessTokenSilently, getIdTokenClaims]);
898
+ const requestEmailVerification = react.useCallback(
899
+ async (options) => {
900
+ if (!isAuthenticated || !auth0User) {
901
+ return {
902
+ success: false,
903
+ status: "failed",
904
+ message: "You must be signed in to verify your email."
905
+ };
906
+ }
907
+ if (auth0User.email_verified === true) {
908
+ return {
909
+ success: true,
910
+ status: "already_verified",
911
+ message: "Your email address is already verified."
912
+ };
913
+ }
914
+ try {
915
+ const response = await client.post("/email/identity/verification-email", {
916
+ return_to: options?.returnTo || window.location.href
917
+ });
918
+ const data = response.data || {};
919
+ return {
920
+ success: true,
921
+ status: data.status || "sent",
922
+ message: data.message || "A verification email has been sent.",
923
+ ...data.retry_after_seconds !== void 0 ? { retryAfterSeconds: data.retry_after_seconds } : {}
924
+ };
925
+ } catch (requestError) {
926
+ if (isAxCloudError(requestError) && requestError.status === 429) {
927
+ const responseDetails = requestError.details?.details;
928
+ const retryAfterSeconds = Number(
929
+ responseDetails && typeof responseDetails === "object" ? responseDetails.retry_after_seconds : void 0
930
+ );
931
+ return {
932
+ success: false,
933
+ status: "rate_limited",
934
+ message: "Please wait before requesting another verification email.",
935
+ ...Number.isFinite(retryAfterSeconds) ? { retryAfterSeconds } : {}
936
+ };
937
+ }
938
+ return {
939
+ success: false,
940
+ status: "failed",
941
+ message: "Failed to send the verification email. Please try again."
942
+ };
943
+ }
944
+ },
945
+ [auth0User, client, isAuthenticated]
946
+ );
661
947
  const getAuth0Client = react.useCallback(() => {
662
948
  return {
663
949
  loginWithRedirect,
@@ -731,24 +1017,28 @@ function useAuth() {
731
1017
  id: auth0User.sub || "",
732
1018
  email: auth0User.email || "",
733
1019
  name: auth0User.name || "",
734
- avatar: auth0User.picture
1020
+ avatar: auth0User.picture,
1021
+ ...typeof auth0User.email_verified === "boolean" ? { emailVerified: auth0User.email_verified } : {}
735
1022
  } : null,
1023
+ needsEmailVerification: isAuthenticated && auth0User?.email_verified === false,
736
1024
  login,
737
1025
  logout,
738
1026
  // Escape hatch for advanced use cases
739
1027
  getAccessToken,
740
1028
  getAuth0Client,
1029
+ refreshUser,
1030
+ requestEmailVerification,
741
1031
  // Password management
742
1032
  requestPasswordReset
743
1033
  };
744
1034
  }
745
1035
  function useUser() {
746
- const { isAuthenticated, isLoading: isAuthLoading } = auth0React.useAuth0();
1036
+ const { isAuthenticated, isLoading: isAuthLoading, user: auth0User } = auth0React.useAuth0();
747
1037
  const { client, stage, orgId } = useAxCloudContext();
748
1038
  const query = reactQuery.useQuery({
749
- queryKey: ["axcloud", "user", "me", stage],
1039
+ queryKey: ["axcloud", "user", "me", stage, orgId, auth0User?.sub],
750
1040
  queryFn: async () => {
751
- return client.get(`/${stage}/api/users/me`);
1041
+ return client.get("/api/users/me");
752
1042
  },
753
1043
  enabled: isAuthenticated && !isAuthLoading,
754
1044
  staleTime: 1e3 * 60 * 5
@@ -757,7 +1047,7 @@ function useUser() {
757
1047
  const userData = query.data;
758
1048
  const userOrgIds = userData?.all_org_ids ?? [];
759
1049
  const isSuperAdmin = userData?.isSuperAdmin === true;
760
- const hasOrgAccess = isSuperAdmin || userOrgIds.includes(orgId);
1050
+ const hasOrgAccess = userOrgIds.includes(orgId);
761
1051
  const orgMembership = userData?.organization_memberships?.[orgId];
762
1052
  const roleInOrg = orgMembership?.role ?? null;
763
1053
  return {
@@ -1375,6 +1665,73 @@ function useDocumentDownload(documentId) {
1375
1665
  refetch: query.refetch
1376
1666
  };
1377
1667
  }
1668
+ function useMemberDocuments(options) {
1669
+ const { client, orgId } = useAxCloudContext();
1670
+ const params = buildDocumentParams(options);
1671
+ const folderId = options?.folderId;
1672
+ const query = reactQuery.useQuery({
1673
+ queryKey: ["axcloud", "documents", "member", "list", orgId, options],
1674
+ queryFn: async () => {
1675
+ return client.get(`/documents/members/${orgId}/documents`, params);
1676
+ },
1677
+ staleTime: 1e3 * 60 * 5
1678
+ });
1679
+ const allItems = query.data?.items ?? [];
1680
+ const items = folderId ? allItems.filter((doc) => doc.folder_ids?.includes(folderId)) : allItems;
1681
+ return {
1682
+ documents: items,
1683
+ items,
1684
+ count: folderId ? items.length : query.data?.count ?? 0,
1685
+ isLoading: query.isLoading,
1686
+ isError: query.isError,
1687
+ error: query.error,
1688
+ refetch: query.refetch
1689
+ };
1690
+ }
1691
+ function useMemberDocumentFolders() {
1692
+ const { client, orgId } = useAxCloudContext();
1693
+ const query = reactQuery.useQuery({
1694
+ queryKey: ["axcloud", "documents", "member", "folders", orgId],
1695
+ queryFn: async () => {
1696
+ return client.get(
1697
+ `/documents/members/${orgId}/document-folders`
1698
+ );
1699
+ },
1700
+ staleTime: 1e3 * 60 * 5
1701
+ });
1702
+ return {
1703
+ folders: query.data?.folders ?? [],
1704
+ isLoading: query.isLoading,
1705
+ isError: query.isError,
1706
+ error: query.error,
1707
+ refetch: query.refetch
1708
+ };
1709
+ }
1710
+ function useMemberDocumentDownload(documentId) {
1711
+ const { client, orgId } = useAxCloudContext();
1712
+ const query = reactQuery.useQuery({
1713
+ queryKey: ["axcloud", "documents", "member", "download", orgId, documentId],
1714
+ queryFn: async () => {
1715
+ return client.get(
1716
+ `/documents/members/${orgId}/documents/${encodeURIComponent(documentId || "")}/download`
1717
+ );
1718
+ },
1719
+ enabled: !!documentId,
1720
+ staleTime: 1e3 * 60 * 10,
1721
+ gcTime: 1e3 * 60 * 14
1722
+ });
1723
+ return {
1724
+ url: query.data?.url ?? null,
1725
+ documentUrl: query.data?.url ?? null,
1726
+ filename: query.data?.filename ?? null,
1727
+ mimeType: query.data?.mimeType ?? null,
1728
+ expiresIn: query.data?.expiresIn ?? null,
1729
+ isLoading: query.isLoading,
1730
+ isError: query.isError,
1731
+ error: query.error,
1732
+ refetch: query.refetch
1733
+ };
1734
+ }
1378
1735
  function useBarnsportMunicipalities() {
1379
1736
  const { client, orgId } = useAxCloudContext();
1380
1737
  const query = reactQuery.useQuery({
@@ -1411,6 +1768,24 @@ function useBarnsportSports() {
1411
1768
  refetch: query.refetch
1412
1769
  };
1413
1770
  }
1771
+ function useBarnsportSport(slug) {
1772
+ const { client, orgId } = useAxCloudContext();
1773
+ const query = reactQuery.useQuery({
1774
+ queryKey: ["axcloud", "barnsport", "sport", orgId, slug],
1775
+ queryFn: () => client.get(
1776
+ `/barnsport/public/${orgId}/sports/${slug || ""}`
1777
+ ),
1778
+ enabled: Boolean(slug),
1779
+ staleTime: 1e3 * 60 * 15
1780
+ });
1781
+ return {
1782
+ sport: query.data?.sport ?? null,
1783
+ isLoading: query.isLoading,
1784
+ isError: query.isError,
1785
+ error: query.error,
1786
+ refetch: query.refetch
1787
+ };
1788
+ }
1414
1789
  function useBarnsportActivities(filters = {}) {
1415
1790
  const { client, orgId } = useAxCloudContext();
1416
1791
  const params = { ...filters };
@@ -1735,12 +2110,19 @@ exports.checkVotingCode = checkVotingCode;
1735
2110
  exports.createClient = createClient;
1736
2111
  exports.createContentSlotReader = createContentSlotReader;
1737
2112
  exports.createFormHelper = createFormHelper;
2113
+ exports.fetchAnalyticsPublicConfig = fetchAnalyticsPublicConfig;
1738
2114
  exports.getBallot = getBallot;
1739
2115
  exports.getClient = getClient;
1740
2116
  exports.getContentSlotMap = getContentSlotMap;
1741
2117
  exports.getVotingReceipt = getVotingReceipt;
2118
+ exports.isAllowedAnalyticsEvent = isAllowedAnalyticsEvent;
1742
2119
  exports.isAxCloudError = isAxCloudError;
2120
+ exports.isLocalAnalyticsHostname = isLocalAnalyticsHostname;
2121
+ exports.sanitizeAnalyticsEventData = sanitizeAnalyticsEventData;
2122
+ exports.sanitizeAnalyticsPath = sanitizeAnalyticsPath;
1743
2123
  exports.submitForm = submitForm;
2124
+ exports.useAnalytics = useAnalytics;
2125
+ exports.useAnalyticsRuntime = useAnalyticsRuntime;
1744
2126
  exports.useAuth = useAuth;
1745
2127
  exports.useAvatar = useAvatar;
1746
2128
  exports.useAxCloudContext = useAxCloudContext;
@@ -1748,6 +2130,7 @@ exports.useBarnsportActivities = useBarnsportActivities;
1748
2130
  exports.useBarnsportActivity = useBarnsportActivity;
1749
2131
  exports.useBarnsportMunicipalities = useBarnsportMunicipalities;
1750
2132
  exports.useBarnsportSitemap = useBarnsportSitemap;
2133
+ exports.useBarnsportSport = useBarnsportSport;
1751
2134
  exports.useBarnsportSports = useBarnsportSports;
1752
2135
  exports.useBranding = useBranding;
1753
2136
  exports.useCodeBallot = useCodeBallot;
@@ -1761,6 +2144,9 @@ exports.useLinkedAccounts = useLinkedAccounts;
1761
2144
  exports.useLogo = useLogo;
1762
2145
  exports.useMedia = useMedia;
1763
2146
  exports.useMediaList = useMediaList;
2147
+ exports.useMemberDocumentDownload = useMemberDocumentDownload;
2148
+ exports.useMemberDocumentFolders = useMemberDocumentFolders;
2149
+ exports.useMemberDocuments = useMemberDocuments;
1764
2150
  exports.useModuleAccess = useModuleAccess;
1765
2151
  exports.useMySection = useMySection;
1766
2152
  exports.useNews = useNews;