@axcode/axcloud-sdk 0.2.0-dev.85285e0 → 0.2.0-dev.d9fb4fe

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 (40) hide show
  1. package/README.md +23 -0
  2. package/dist/barnsport.d.mts +12 -3
  3. package/dist/barnsport.d.ts +12 -3
  4. package/dist/barnsport.js +21 -17
  5. package/dist/barnsport.mjs +2 -2
  6. package/dist/{chunk-DI4M6A7K.js → chunk-2IVJTMRB.js} +264 -219
  7. package/dist/chunk-2IVJTMRB.js.map +1 -0
  8. package/dist/{chunk-HRNRGCCT.mjs → chunk-7IPCZJ5Q.mjs} +16 -5
  9. package/dist/chunk-7IPCZJ5Q.mjs.map +1 -0
  10. package/dist/chunk-7K5N3DQ4.js +231 -0
  11. package/dist/chunk-7K5N3DQ4.js.map +1 -0
  12. package/dist/{chunk-F3JPEND3.mjs → chunk-CACQMQCJ.mjs} +259 -214
  13. package/dist/chunk-CACQMQCJ.mjs.map +1 -0
  14. package/dist/chunk-PMMCOWL3.mjs +223 -0
  15. package/dist/chunk-PMMCOWL3.mjs.map +1 -0
  16. package/dist/{chunk-EX66R5IA.js → chunk-ZOQAXLCZ.js} +29 -17
  17. package/dist/chunk-ZOQAXLCZ.js.map +1 -0
  18. package/dist/index.d.mts +4 -79
  19. package/dist/index.d.ts +4 -79
  20. package/dist/index.js +81 -320
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +6 -260
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/public.d.mts +2 -2
  25. package/dist/public.d.ts +2 -2
  26. package/dist/public.js +29 -9
  27. package/dist/public.mjs +4 -4
  28. package/dist/{useBarnsport-1DObGZDl.d.mts → useBarnsport-Cn9flax0.d.mts} +54 -6
  29. package/dist/{useBarnsport-1DObGZDl.d.ts → useBarnsport-Cn9flax0.d.ts} +54 -6
  30. package/dist/{analytics-LYZxP7PC.d.mts → useContent-1WbKvPY4.d.mts} +77 -1
  31. package/dist/{analytics-BOxmSWNt.d.ts → useContent-Cl7dvERE.d.ts} +77 -1
  32. package/package.json +1 -1
  33. package/dist/chunk-2A5NJAFA.mjs +0 -15
  34. package/dist/chunk-2A5NJAFA.mjs.map +0 -1
  35. package/dist/chunk-DI4M6A7K.js.map +0 -1
  36. package/dist/chunk-DSWRJZWR.js +0 -18
  37. package/dist/chunk-DSWRJZWR.js.map +0 -1
  38. package/dist/chunk-EX66R5IA.js.map +0 -1
  39. package/dist/chunk-F3JPEND3.mjs.map +0 -1
  40. package/dist/chunk-HRNRGCCT.mjs.map +0 -1
@@ -1,215 +1,6 @@
1
- import { useAxCloudContext } from './chunk-2A5NJAFA.mjs';
1
+ import { useAxCloudContext, isAxCloudError } from './chunk-PMMCOWL3.mjs';
2
2
  import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
3
-
4
- // src/core/errors.ts
5
- var AxCloudError = class _AxCloudError extends Error {
6
- constructor(message, code, status, details) {
7
- super(message);
8
- this.name = "AxCloudError";
9
- this.code = code;
10
- this.status = status;
11
- this.details = details;
12
- const ErrorWithCapture = Error;
13
- if (ErrorWithCapture.captureStackTrace) {
14
- ErrorWithCapture.captureStackTrace(this, _AxCloudError);
15
- }
16
- }
17
- static fromResponse(status, body) {
18
- const details = typeof body === "object" ? body : void 0;
19
- const message = (typeof details?.message === "string" ? details.message : void 0) || (typeof details?.error === "string" ? details.error : void 0);
20
- switch (status) {
21
- case 401:
22
- return new _AxCloudError(
23
- message || "Authentication required",
24
- "UNAUTHORIZED",
25
- status,
26
- details
27
- );
28
- case 403:
29
- return new _AxCloudError(message || "Access denied", "FORBIDDEN", status, details);
30
- case 404:
31
- return new _AxCloudError(message || "Resource not found", "NOT_FOUND", status, details);
32
- case 422:
33
- return new _AxCloudError(
34
- message || "Validation failed",
35
- "VALIDATION_ERROR",
36
- status,
37
- details
38
- );
39
- default:
40
- if (status >= 500) {
41
- return new _AxCloudError(message || "Server error", "SERVER_ERROR", status, details);
42
- }
43
- return new _AxCloudError(message || "An error occurred", "UNKNOWN_ERROR", status, details);
44
- }
45
- }
46
- static networkError(originalError) {
47
- const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
48
- const message = isDev && originalError?.message ? originalError.message : "Network request failed";
49
- return new _AxCloudError(
50
- message,
51
- "NETWORK_ERROR",
52
- 0,
53
- isDev ? { originalError: originalError?.message } : void 0
54
- );
55
- }
56
- static timeoutError(timeoutMs) {
57
- return new _AxCloudError(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", 0, {
58
- timeout: timeoutMs
59
- });
60
- }
61
- };
62
- function isAxCloudError(error) {
63
- return error instanceof AxCloudError;
64
- }
65
-
66
- // src/core/client.ts
67
- var AxCloudClient = class {
68
- constructor(config) {
69
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
70
- this.getAccessToken = config.getAccessToken;
71
- this.apiKey = config.apiKey;
72
- this.defaultTimeout = config.timeout ?? 3e4;
73
- }
74
- /**
75
- * Update the access token getter (used when auth state changes)
76
- */
77
- setAccessTokenGetter(getter) {
78
- this.getAccessToken = getter;
79
- }
80
- /**
81
- * Build URL with query parameters
82
- */
83
- buildUrl(path, params) {
84
- const url = new URL(`${this.baseUrl}${path}`);
85
- if (params) {
86
- Object.entries(params).forEach(([key, value]) => {
87
- if (value !== void 0) {
88
- url.searchParams.append(key, String(value));
89
- }
90
- });
91
- }
92
- return url.toString();
93
- }
94
- /**
95
- * API key should only be sent to public endpoints.
96
- * This avoids leaking public keys to authenticated/internal routes.
97
- */
98
- shouldAttachApiKey(path) {
99
- const normalized = path.startsWith("/") ? path : `/${path}`;
100
- return normalized.startsWith("/public/") || normalized.startsWith("/api/public/") || normalized.startsWith("/content/public/") || normalized.startsWith("/media/public/") || normalized.startsWith("/documents/public/") || normalized.startsWith("/barnsport/public/") || normalized.startsWith("/api/barnsport/public/");
101
- }
102
- /**
103
- * Make an authenticated request
104
- */
105
- async request(path, options = {}) {
106
- const { body, params, headers: customHeaders, timeout, ...restOptions } = options;
107
- const headers = {
108
- "Content-Type": "application/json"
109
- };
110
- if (customHeaders) {
111
- const customHeadersRecord = customHeaders;
112
- Object.assign(headers, customHeadersRecord);
113
- }
114
- if (this.apiKey && this.shouldAttachApiKey(path)) {
115
- headers["x-api-key"] = this.apiKey;
116
- }
117
- if (this.getAccessToken) {
118
- try {
119
- const token = await this.getAccessToken();
120
- if (token) {
121
- headers["Authorization"] = `Bearer ${token}`;
122
- }
123
- } catch (error) {
124
- if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
125
- console.warn(
126
- "[AxCloud SDK] Failed to fetch access token:",
127
- error instanceof Error ? error.message : error
128
- );
129
- }
130
- }
131
- }
132
- const url = this.buildUrl(path, params);
133
- const controller = new AbortController();
134
- const requestTimeout = timeout ?? this.defaultTimeout;
135
- const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
136
- try {
137
- const response = await fetch(url, {
138
- ...restOptions,
139
- headers,
140
- body: body ? JSON.stringify(body) : void 0,
141
- signal: controller.signal
142
- });
143
- const contentType = response.headers.get("content-type");
144
- const isJson = contentType?.includes("application/json");
145
- if (!response.ok) {
146
- const errorBody = isJson ? await response.json().catch(() => null) : null;
147
- throw AxCloudError.fromResponse(response.status, errorBody);
148
- }
149
- if (response.status === 204) {
150
- return {};
151
- }
152
- return isJson ? await response.json() : {};
153
- } catch (error) {
154
- if (error instanceof AxCloudError) {
155
- throw error;
156
- }
157
- if (error instanceof Error && error.name === "AbortError") {
158
- throw AxCloudError.timeoutError(requestTimeout);
159
- }
160
- throw AxCloudError.networkError(error instanceof Error ? error : void 0);
161
- } finally {
162
- clearTimeout(timeoutId);
163
- }
164
- }
165
- /**
166
- * GET request
167
- */
168
- get(path, params) {
169
- return this.request(path, { method: "GET", params });
170
- }
171
- /**
172
- * POST request
173
- */
174
- post(path, body) {
175
- return this.request(path, { method: "POST", body });
176
- }
177
- /**
178
- * PUT request
179
- */
180
- put(path, body) {
181
- return this.request(path, { method: "PUT", body });
182
- }
183
- /**
184
- * PATCH request
185
- */
186
- patch(path, body) {
187
- return this.request(path, { method: "PATCH", body });
188
- }
189
- /**
190
- * DELETE request
191
- */
192
- delete(path) {
193
- return this.request(path, { method: "DELETE" });
194
- }
195
- };
196
- var clientRegistry = /* @__PURE__ */ new WeakMap();
197
- function createClient(config, key) {
198
- const client = new AxCloudClient(config);
199
- if (key) {
200
- clientRegistry.set(key, client);
201
- }
202
- return client;
203
- }
204
- function getClient(key) {
205
- if (key) {
206
- const client = clientRegistry.get(key);
207
- if (client) {
208
- return client;
209
- }
210
- }
211
- throw new Error("AxCloud client not found. Make sure AxCloudProvider is mounted and use useAxCloudContext() to get the client.");
212
- }
3
+ import { useQuery } from '@tanstack/react-query';
213
4
 
214
5
  // src/core/analytics.ts
215
6
  var EVENT_NAME_PATTERN = /^[a-z][a-z0-9_]{1,63}$/;
@@ -334,6 +125,90 @@ function sendAnalyticsEvent(eventName, data, allowedEvents, targetWindow = windo
334
125
  umami.track(eventName, sanitizeAnalyticsEventData(data));
335
126
  return true;
336
127
  }
128
+
129
+ // src/core/contentSlots.ts
130
+ var SLOT_ATTRIBUTE_KEYS = ["slot", "field", "key", "name"];
131
+ function getContentSlotMap(content) {
132
+ const fields = isRecord(content?.fields) ? { ...content?.fields } : {};
133
+ for (const block of content?.blocks || []) {
134
+ const slot = getBlockSlot(block);
135
+ if (!slot) continue;
136
+ if (!(slot in fields)) fields[slot] = blockToSlotValue(block);
137
+ }
138
+ return fields;
139
+ }
140
+ function createContentSlotReader(content) {
141
+ const fields = getContentSlotMap(content);
142
+ const value = (key, fallback) => {
143
+ return key in fields ? fields[key] : fallback;
144
+ };
145
+ const unsafeHtml = (key, fallback = "") => stringifySlotValue(value(key, fallback));
146
+ return {
147
+ fields,
148
+ value,
149
+ text: (key, fallback = "") => stringifySlotValue(value(key, fallback)),
150
+ html: unsafeHtml,
151
+ unsafeHtml,
152
+ list: (key, fallback = []) => slotValueToList(value(key, fallback)),
153
+ image: (key, fallback) => slotValueToImage(value(key, fallback))
154
+ };
155
+ }
156
+ function getBlockSlot(block) {
157
+ const attributes = block.attributes || {};
158
+ for (const key of SLOT_ATTRIBUTE_KEYS) {
159
+ const value = attributes[key];
160
+ if (typeof value === "string" && value.trim()) return value.trim();
161
+ }
162
+ return void 0;
163
+ }
164
+ function blockToSlotValue(block) {
165
+ if (block.attributes && "value" in block.attributes) {
166
+ return block.attributes.value;
167
+ }
168
+ if (block.type === "list") {
169
+ return Array.isArray(block.items) ? block.items : [];
170
+ }
171
+ if (block.type === "image" && block.url) {
172
+ return {
173
+ url: block.url,
174
+ alt: block.alt,
175
+ caption: block.caption
176
+ };
177
+ }
178
+ return block.content ?? "";
179
+ }
180
+ function stringifySlotValue(value) {
181
+ if (value === void 0 || value === null) return "";
182
+ if (typeof value === "string") return value;
183
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
184
+ if (Array.isArray(value)) return value.map((item) => stringifySlotValue(item)).filter(Boolean).join("\n");
185
+ return "";
186
+ }
187
+ function slotValueToList(value) {
188
+ if (Array.isArray(value)) {
189
+ return value.map((item) => stringifySlotValue(item)).filter(Boolean);
190
+ }
191
+ if (typeof value === "string") {
192
+ return value.split(/\r?\n/).map((item) => item.trim()).filter(Boolean);
193
+ }
194
+ return [];
195
+ }
196
+ function slotValueToImage(value) {
197
+ if (isRecord(value) && typeof value.url === "string") {
198
+ return {
199
+ url: value.url,
200
+ alt: typeof value.alt === "string" ? value.alt : void 0,
201
+ caption: typeof value.caption === "string" ? value.caption : void 0
202
+ };
203
+ }
204
+ if (typeof value === "string" && value) {
205
+ return { url: value };
206
+ }
207
+ return void 0;
208
+ }
209
+ function isRecord(value) {
210
+ return !!value && typeof value === "object" && !Array.isArray(value);
211
+ }
337
212
  var NAVIGATION_EVENT = "axcloud-sdk:navigation";
338
213
  var historySubscriberCount = 0;
339
214
  var originalPushState = null;
@@ -456,6 +331,176 @@ function useAnalytics() {
456
331
  return useAxCloudContext().analytics;
457
332
  }
458
333
 
459
- export { AxCloudClient, AxCloudError, createClient, fetchAnalyticsPublicConfig, getClient, isAllowedAnalyticsEvent, isAxCloudError, isLocalAnalyticsHostname, sanitizeAnalyticsEventData, sanitizeAnalyticsPath, useAnalytics, useAnalyticsRuntime };
460
- //# sourceMappingURL=chunk-F3JPEND3.mjs.map
461
- //# sourceMappingURL=chunk-F3JPEND3.mjs.map
334
+ // src/react/contentQueryPolicy.ts
335
+ var CONTENT_STALE_TIME_MS = 6e4;
336
+ function shouldRetryContentRequest(failureCount, error) {
337
+ if (isAxCloudError(error) && error.status >= 400 && error.status < 500) {
338
+ return false;
339
+ }
340
+ return failureCount < 2;
341
+ }
342
+ function normalizeContentCollectionType(contentType) {
343
+ switch (contentType.toLowerCase()) {
344
+ case "news":
345
+ return "news";
346
+ case "page":
347
+ case "pages":
348
+ return "pages";
349
+ case "event":
350
+ case "events":
351
+ return "events";
352
+ default:
353
+ throw new Error(`Unsupported AxCloud content collection type: ${contentType}`);
354
+ }
355
+ }
356
+ function normalizeContentDetailType(contentType) {
357
+ switch (contentType.toLowerCase()) {
358
+ case "news":
359
+ return "news";
360
+ case "page":
361
+ case "pages":
362
+ return "page";
363
+ case "event":
364
+ case "events":
365
+ return "event";
366
+ default:
367
+ throw new Error(`Unsupported AxCloud content detail type: ${contentType}`);
368
+ }
369
+ }
370
+ function getContentAccessState(context, publicOnly) {
371
+ if (publicOnly) {
372
+ return { mode: "public", enabled: true, subject: "anonymous" };
373
+ }
374
+ const isLoading = context.isAuthLoading ?? false;
375
+ if (isLoading) {
376
+ return { mode: "pending", enabled: false, subject: "auth-loading" };
377
+ }
378
+ const hasExplicitAuthState = typeof context.isAuthenticated === "boolean";
379
+ const isAuthenticated = context.isAuthenticated ?? !context.isPublicMode;
380
+ if (!isAuthenticated) {
381
+ return { mode: "public", enabled: true, subject: "anonymous" };
382
+ }
383
+ if (hasExplicitAuthState && !context.authSubject) {
384
+ return { mode: "pending", enabled: false, subject: "auth-subject-pending" };
385
+ }
386
+ const subject = context.authSubject || "legacy-authenticated-session";
387
+ return { mode: "member", enabled: Boolean(subject), subject };
388
+ }
389
+
390
+ // src/react/hooks/useContent.ts
391
+ function useContent(contentType, options = {}) {
392
+ const context = useAxCloudContext();
393
+ const { client, config, orgId, stage } = context;
394
+ const collectionType = normalizeContentCollectionType(contentType);
395
+ const {
396
+ publicOnly = false,
397
+ page = 1,
398
+ pageSize = 20,
399
+ search,
400
+ sortBy = collectionType === "news" ? "publishedAt" : "createdAt",
401
+ sortOrder = "desc",
402
+ tags,
403
+ lang
404
+ } = options;
405
+ const access = getContentAccessState(context, publicOnly);
406
+ const deliveryScope = access.mode === "member" ? "members" : "public";
407
+ const params = {
408
+ page,
409
+ pageSize,
410
+ search,
411
+ sort: sortBy,
412
+ order: sortOrder,
413
+ tags: tags?.length ? tags.join(",") : void 0,
414
+ lang
415
+ };
416
+ const query = useQuery({
417
+ queryKey: [
418
+ "axcloud",
419
+ "content",
420
+ "collection",
421
+ stage,
422
+ config.apiUrl,
423
+ orgId,
424
+ access.mode,
425
+ access.subject,
426
+ collectionType,
427
+ params
428
+ ],
429
+ queryFn: () => client.get(
430
+ `/content/${deliveryScope}/${orgId}/${collectionType}`,
431
+ params
432
+ ),
433
+ enabled: access.enabled,
434
+ staleTime: CONTENT_STALE_TIME_MS,
435
+ refetchOnWindowFocus: true,
436
+ retry: shouldRetryContentRequest
437
+ });
438
+ const items = query.data?.items ?? [];
439
+ return {
440
+ data: items,
441
+ count: query.data?.count ?? items.length,
442
+ total: query.data?.total ?? items.length,
443
+ page: query.data?.page ?? page,
444
+ pageSize: query.data?.pageSize ?? pageSize,
445
+ hasMore: query.data?.hasMore ?? false,
446
+ nextCursor: query.data?.nextCursor,
447
+ isLoading: access.mode === "pending" || query.isLoading,
448
+ isFetching: query.isFetching,
449
+ isError: query.isError,
450
+ error: query.error,
451
+ refetch: query.refetch
452
+ };
453
+ }
454
+ function useContentItem(contentType, idOrSlug, options = {}) {
455
+ const context = useAxCloudContext();
456
+ const { client, config, orgId, stage } = context;
457
+ const detailType = normalizeContentDetailType(contentType);
458
+ const { publicOnly = false, lang } = options;
459
+ const access = getContentAccessState(context, publicOnly);
460
+ const deliveryScope = access.mode === "member" ? "members" : "public";
461
+ const query = useQuery({
462
+ queryKey: [
463
+ "axcloud",
464
+ "content",
465
+ "item",
466
+ stage,
467
+ config.apiUrl,
468
+ orgId,
469
+ access.mode,
470
+ access.subject,
471
+ detailType,
472
+ idOrSlug,
473
+ lang
474
+ ],
475
+ queryFn: () => {
476
+ const encodedIdOrSlug = encodeURIComponent(idOrSlug);
477
+ const endpoint = `/content/${deliveryScope}/${orgId}/items/${detailType}/${encodedIdOrSlug}`;
478
+ return lang ? client.get(endpoint, { lang }) : client.get(endpoint);
479
+ },
480
+ enabled: access.enabled && Boolean(idOrSlug),
481
+ staleTime: CONTENT_STALE_TIME_MS,
482
+ refetchOnWindowFocus: true,
483
+ retry: shouldRetryContentRequest
484
+ });
485
+ return {
486
+ data: query.data ?? null,
487
+ isLoading: access.mode === "pending" || query.isLoading,
488
+ isFetching: query.isFetching,
489
+ isError: query.isError,
490
+ error: query.error,
491
+ refetch: query.refetch
492
+ };
493
+ }
494
+ function usePageContent(slug, options = {}) {
495
+ const state = useContentItem("page", slug, options);
496
+ const reader = useMemo(() => createContentSlotReader(state.data), [state.data]);
497
+ return {
498
+ ...state,
499
+ page: state.data,
500
+ ...reader
501
+ };
502
+ }
503
+
504
+ export { createContentSlotReader, fetchAnalyticsPublicConfig, getContentSlotMap, isAllowedAnalyticsEvent, isLocalAnalyticsHostname, sanitizeAnalyticsEventData, sanitizeAnalyticsPath, useAnalytics, useAnalyticsRuntime, useContent, useContentItem, usePageContent };
505
+ //# sourceMappingURL=chunk-CACQMQCJ.mjs.map
506
+ //# sourceMappingURL=chunk-CACQMQCJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/analytics.ts","../src/core/contentSlots.ts","../src/react/analytics.ts","../src/react/contentQueryPolicy.ts","../src/react/hooks/useContent.ts"],"names":["useMemo"],"mappings":"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","file":"chunk-CACQMQCJ.mjs","sourcesContent":["export type AnalyticsEventValue = string | number | boolean;\nexport type AnalyticsEventData = Record<string, AnalyticsEventValue>;\n\nexport interface AxCloudAnalyticsOptions {\n /** Site key configured in AxCloud, for example \"public-web\". */\n siteKey: string;\n /** Analytics is opt-in and disabled unless this is true. */\n enabled?: boolean;\n /** Allow local collection for explicit development tests. */\n trackLocalhost?: boolean;\n /** Override path normalization. Return null to skip a pageview. */\n normalizePath?: (pathname: string) => string | null;\n}\n\nexport interface AnalyticsPublicConfig {\n enabled: boolean;\n provider?: 'umami';\n websiteId?: string;\n scriptUrl?: string;\n hostUrl?: string;\n domains?: string[];\n autoTrack?: boolean;\n respectDoNotTrack?: boolean;\n excludeSearch?: boolean;\n excludeHash?: boolean;\n allowedEvents?: string[];\n}\n\nexport interface AnalyticsRuntime {\n enabled: boolean;\n ready: boolean;\n track: (eventName: string, data?: AnalyticsEventData) => boolean;\n trackPageView: (pathname?: string) => boolean;\n}\n\ninterface UmamiWindow extends Window {\n umami?: {\n track: (\n event?: string | { url?: string; title?: string },\n data?: AnalyticsEventData\n ) => unknown;\n };\n}\n\nconst EVENT_NAME_PATTERN = /^[a-z][a-z0-9_]{1,63}$/;\nconst PROPERTY_KEY_PATTERN = /^[a-z][a-z0-9_]{0,47}$/;\nconst SENSITIVE_PROPERTY_PATTERN =\n /(^|_)(auth0|email|name|password|query|search|secret|token|trace|user|userid)($|_)/;\nconst EMAIL_VALUE_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst OPAQUE_SEGMENT_PATTERNS = [\n /^[0-9a-f]{8}-[0-9a-f-]{27,}$/i,\n /^(org|user|section|document|content|poll|invitation|invite|trace|chan)[_-][a-z0-9_-]+$/i,\n /^[a-f0-9]{20,}$/i,\n /^[a-z0-9_-]{32,}$/i,\n];\n\nconst scriptLoads = new Map<string, Promise<void>>();\n\nexport function isLocalAnalyticsHostname(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';\n}\n\nexport function sanitizeAnalyticsPath(\n pathname: string,\n customNormalizer?: (pathname: string) => string | null\n): string | null {\n const rawPath = pathname.split(/[?#]/, 1)[0] || '/';\n const normalizedInput = rawPath.startsWith('/') ? rawPath : `/${rawPath}`;\n const custom = customNormalizer?.(normalizedInput);\n if (custom === null) return null;\n const path = custom ?? normalizedInput;\n const cleanPath = path.split(/[?#]/, 1)[0] || '/';\n\n const segments = cleanPath.split('/').map((segment) => {\n if (!segment) return segment;\n let decoded = segment;\n try {\n decoded = decodeURIComponent(segment);\n } catch {\n // Keep malformed path segments encoded and classify them below.\n }\n return OPAQUE_SEGMENT_PATTERNS.some((pattern) => pattern.test(decoded)) ? ':id' : segment;\n });\n\n return segments.join('/') || '/';\n}\n\nexport function sanitizeAnalyticsEventData(\n data: AnalyticsEventData | undefined\n): AnalyticsEventData | undefined {\n if (!data) return undefined;\n const sanitized: AnalyticsEventData = {};\n\n for (const [rawKey, rawValue] of Object.entries(data).slice(0, 20)) {\n const key = rawKey.trim().toLowerCase();\n if (!PROPERTY_KEY_PATTERN.test(key) || SENSITIVE_PROPERTY_PATTERN.test(key)) continue;\n\n if (typeof rawValue === 'string') {\n const value = rawValue.trim();\n if (!value || value.length > 100 || EMAIL_VALUE_PATTERN.test(value)) continue;\n sanitized[key] = value;\n continue;\n }\n if (typeof rawValue === 'number' && Number.isFinite(rawValue)) {\n sanitized[key] = rawValue;\n continue;\n }\n if (typeof rawValue === 'boolean') sanitized[key] = rawValue;\n }\n\n return Object.keys(sanitized).length > 0 ? sanitized : undefined;\n}\n\nexport function isAllowedAnalyticsEvent(\n eventName: string,\n allowedEvents: string[] | undefined\n): boolean {\n return EVENT_NAME_PATTERN.test(eventName) && Boolean(allowedEvents?.includes(eventName));\n}\n\nexport async function fetchAnalyticsPublicConfig(input: {\n apiUrl: string;\n orgId: string;\n siteKey: string;\n stage: string;\n hostname: string;\n signal?: AbortSignal;\n}): Promise<AnalyticsPublicConfig> {\n const baseUrl = input.apiUrl.replace(/\\/$/, '');\n const url = new URL(`${baseUrl}/analytics/public/config`);\n url.searchParams.set('orgId', input.orgId);\n url.searchParams.set('siteKey', input.siteKey);\n url.searchParams.set('stage', input.stage);\n url.searchParams.set('hostname', input.hostname);\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: input.signal,\n });\n if (!response.ok) throw new Error(`Analytics configuration returned ${response.status}`);\n return response.json() as Promise<AnalyticsPublicConfig>;\n}\n\nexport function loadAnalyticsScript(\n config: AnalyticsPublicConfig,\n doc: Document = document\n): Promise<void> {\n if (!config.enabled || !config.websiteId || !config.scriptUrl) {\n return Promise.reject(new Error('Analytics tracker configuration is incomplete'));\n }\n\n const key = `${config.scriptUrl}|${config.websiteId}`;\n const existingPromise = scriptLoads.get(key);\n if (existingPromise) return existingPromise;\n\n const existing = doc.querySelector<HTMLScriptElement>(\n `script[data-axcloud-analytics-site=\"${config.websiteId}\"]`\n );\n if (existing && (doc.defaultView as UmamiWindow | null)?.umami) {\n return Promise.resolve();\n }\n\n const promise = new Promise<void>((resolve, reject) => {\n const script = existing || doc.createElement('script');\n const onLoad = () => resolve();\n const onError = () => reject(new Error('Analytics tracker failed to load'));\n script.addEventListener('load', onLoad, { once: true });\n script.addEventListener('error', onError, { once: true });\n\n if (!existing) {\n script.src = config.scriptUrl as string;\n script.defer = true;\n script.dataset.websiteId = config.websiteId as string;\n script.dataset.axcloudAnalyticsSite = config.websiteId as string;\n script.dataset.autoTrack = String(config.autoTrack === true);\n if (config.hostUrl) script.dataset.hostUrl = config.hostUrl;\n if (config.domains?.length) script.dataset.domains = config.domains.join(',');\n if (config.respectDoNotTrack !== false) script.dataset.doNotTrack = 'true';\n if (config.excludeSearch !== false) script.dataset.excludeSearch = 'true';\n if (config.excludeHash !== false) script.dataset.excludeHash = 'true';\n doc.head.appendChild(script);\n }\n }).catch((error) => {\n scriptLoads.delete(key);\n throw error;\n });\n\n scriptLoads.set(key, promise);\n return promise;\n}\n\nexport function sendAnalyticsPageView(\n pathname: string,\n options: AxCloudAnalyticsOptions,\n targetWindow: Window = window\n): boolean {\n const path = sanitizeAnalyticsPath(pathname, options.normalizePath);\n const umami = (targetWindow as UmamiWindow).umami;\n if (!path || !umami) return false;\n umami.track({ url: path, title: targetWindow.document.title });\n return true;\n}\n\nexport function sendAnalyticsEvent(\n eventName: string,\n data: AnalyticsEventData | undefined,\n allowedEvents: string[] | undefined,\n targetWindow: Window = window\n): boolean {\n const umami = (targetWindow as UmamiWindow).umami;\n if (!umami || !isAllowedAnalyticsEvent(eventName, allowedEvents)) return false;\n umami.track(eventName, sanitizeAnalyticsEventData(data));\n return true;\n}\n","import type { ContentBlock, ContentItem } from './types'\n\nexport type ContentSlotValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | string[]\n | Record<string, unknown>\n | unknown[]\n\nexport type ContentSlotMap = Record<string, ContentSlotValue>\n\nexport interface ContentSlotImage {\n url: string\n alt?: string\n caption?: string\n}\n\nexport interface ContentSlotReader {\n fields: ContentSlotMap\n value<T = ContentSlotValue>(key: string, fallback?: T): ContentSlotValue | T\n text(key: string, fallback?: string): string\n /** @deprecated HTML is untrusted. Prefer text(), or unsafeHtml() with sanitization. */\n html(key: string, fallback?: string): string\n /** Returns untrusted CMS HTML. Sanitize it before inserting it into the DOM. */\n unsafeHtml(key: string, fallback?: string): string\n list(key: string, fallback?: string[]): string[]\n image(key: string, fallback?: ContentSlotImage): ContentSlotImage | undefined\n}\n\nconst SLOT_ATTRIBUTE_KEYS = ['slot', 'field', 'key', 'name']\n\nexport function getContentSlotMap(content?: Pick<ContentItem, 'fields' | 'blocks'> | null): ContentSlotMap {\n const fields: ContentSlotMap = isRecord(content?.fields) ? { ...(content?.fields as ContentSlotMap) } : {}\n\n for (const block of content?.blocks || []) {\n const slot = getBlockSlot(block)\n if (!slot) continue\n // Explicit structured fields are authoritative. Slotted blocks provide a\n // backwards-compatible fallback only.\n if (!(slot in fields)) fields[slot] = blockToSlotValue(block)\n }\n\n return fields\n}\n\nexport function createContentSlotReader(content?: Pick<ContentItem, 'fields' | 'blocks'> | null): ContentSlotReader {\n const fields = getContentSlotMap(content)\n\n const value = <T = ContentSlotValue>(key: string, fallback?: T): ContentSlotValue | T => {\n return key in fields ? fields[key] : (fallback as T)\n }\n\n const unsafeHtml = (key: string, fallback = '') => stringifySlotValue(value(key, fallback))\n\n return {\n fields,\n value,\n text: (key, fallback = '') => stringifySlotValue(value(key, fallback)),\n html: unsafeHtml,\n unsafeHtml,\n list: (key, fallback = []) => slotValueToList(value(key, fallback)),\n image: (key, fallback) => slotValueToImage(value(key, fallback)),\n }\n}\n\nfunction getBlockSlot(block: ContentBlock): string | undefined {\n const attributes = block.attributes || {}\n\n for (const key of SLOT_ATTRIBUTE_KEYS) {\n const value = attributes[key]\n if (typeof value === 'string' && value.trim()) return value.trim()\n }\n\n return undefined\n}\n\nfunction blockToSlotValue(block: ContentBlock): ContentSlotValue {\n if (block.attributes && 'value' in block.attributes) {\n return block.attributes.value as ContentSlotValue\n }\n\n if (block.type === 'list') {\n return Array.isArray(block.items) ? block.items : []\n }\n\n if (block.type === 'image' && block.url) {\n return {\n url: block.url,\n alt: block.alt,\n caption: block.caption,\n }\n }\n\n return block.content ?? ''\n}\n\nfunction stringifySlotValue(value: unknown): string {\n if (value === undefined || value === null) return ''\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n if (Array.isArray(value)) return value.map((item) => stringifySlotValue(item)).filter(Boolean).join('\\n')\n return ''\n}\n\nfunction slotValueToList(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.map((item) => stringifySlotValue(item)).filter(Boolean)\n }\n\n if (typeof value === 'string') {\n return value\n .split(/\\r?\\n/)\n .map((item) => item.trim())\n .filter(Boolean)\n }\n\n return []\n}\n\nfunction slotValueToImage(value: unknown): ContentSlotImage | undefined {\n if (isRecord(value) && typeof value.url === 'string') {\n return {\n url: value.url,\n alt: typeof value.alt === 'string' ? value.alt : undefined,\n caption: typeof value.caption === 'string' ? value.caption : undefined,\n }\n }\n\n if (typeof value === 'string' && value) {\n return { url: value }\n }\n\n return undefined\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { AxCloudConfig } from '../core/types';\nimport { useAxCloudContext } from './context';\nimport {\n fetchAnalyticsPublicConfig,\n isLocalAnalyticsHostname,\n loadAnalyticsScript,\n sendAnalyticsEvent,\n sendAnalyticsPageView,\n type AnalyticsEventData,\n type AnalyticsPublicConfig,\n type AnalyticsRuntime,\n} from '../core/analytics';\n\nconst NAVIGATION_EVENT = 'axcloud-sdk:navigation';\nlet historySubscriberCount = 0;\nlet originalPushState: History['pushState'] | null = null;\nlet originalReplaceState: History['replaceState'] | null = null;\n\nexport type AnalyticsRuntimeConfig = Pick<\n AxCloudConfig,\n 'analytics' | 'apiUrl' | 'orgId' | 'stage'\n>;\n\nfunction subscribeToNavigation(callback: () => void): () => void {\n if (typeof window === 'undefined') return () => undefined;\n\n if (historySubscriberCount === 0) {\n originalPushState = window.history.pushState.bind(window.history);\n originalReplaceState = window.history.replaceState.bind(window.history);\n window.history.pushState = ((...args: Parameters<History['pushState']>) => {\n originalPushState?.(...args);\n window.dispatchEvent(new Event(NAVIGATION_EVENT));\n }) as History['pushState'];\n window.history.replaceState = ((...args: Parameters<History['replaceState']>) => {\n originalReplaceState?.(...args);\n window.dispatchEvent(new Event(NAVIGATION_EVENT));\n }) as History['replaceState'];\n }\n historySubscriberCount += 1;\n window.addEventListener('popstate', callback);\n window.addEventListener(NAVIGATION_EVENT, callback);\n\n return () => {\n window.removeEventListener('popstate', callback);\n window.removeEventListener(NAVIGATION_EVENT, callback);\n historySubscriberCount = Math.max(0, historySubscriberCount - 1);\n if (historySubscriberCount === 0) {\n if (originalPushState) window.history.pushState = originalPushState;\n if (originalReplaceState) window.history.replaceState = originalReplaceState;\n originalPushState = null;\n originalReplaceState = null;\n }\n };\n}\n\nfunction doNotTrackEnabled(config: AnalyticsPublicConfig): boolean {\n if (config.respectDoNotTrack === false || typeof navigator === 'undefined') return false;\n return navigator.doNotTrack === '1';\n}\n\nexport function useAnalyticsRuntime(config: AnalyticsRuntimeConfig): AnalyticsRuntime {\n const [enabled, setEnabled] = useState(false);\n const [ready, setReady] = useState(false);\n const publicConfigRef = useRef<AnalyticsPublicConfig | null>(null);\n const optionsRef = useRef(config.analytics);\n optionsRef.current = config.analytics;\n\n const trackPageView = useCallback(\n (pathname?: string) => {\n if (!ready || !optionsRef.current || typeof window === 'undefined') return false;\n return sendAnalyticsPageView(pathname || window.location.pathname, optionsRef.current);\n },\n [ready]\n );\n\n const track = useCallback(\n (eventName: string, data?: AnalyticsEventData) => {\n if (!ready || typeof window === 'undefined') return false;\n return sendAnalyticsEvent(eventName, data, publicConfigRef.current?.allowedEvents);\n },\n [ready]\n );\n\n useEffect(() => {\n const options = config.analytics;\n setEnabled(false);\n setReady(false);\n publicConfigRef.current = null;\n\n if (!options?.enabled || !options.siteKey || typeof window === 'undefined') return undefined;\n if (isLocalAnalyticsHostname(window.location.hostname) && !options.trackLocalhost)\n return undefined;\n\n const controller = new AbortController();\n let cancelled = false;\n let unsubscribe: () => void = () => undefined;\n\n const initialize = async () => {\n try {\n const publicConfig = await fetchAnalyticsPublicConfig({\n apiUrl: config.apiUrl,\n orgId: config.orgId,\n siteKey: options.siteKey,\n stage: config.stage,\n hostname: window.location.hostname,\n signal: controller.signal,\n });\n if (cancelled || !publicConfig.enabled || doNotTrackEnabled(publicConfig)) return;\n\n publicConfigRef.current = publicConfig;\n setEnabled(true);\n await loadAnalyticsScript(publicConfig);\n if (cancelled) return;\n setReady(true);\n\n if (!publicConfig.autoTrack) {\n const trackCurrentPage = () => {\n sendAnalyticsPageView(window.location.pathname, options);\n };\n trackCurrentPage();\n unsubscribe = subscribeToNavigation(trackCurrentPage);\n }\n } catch (error) {\n if (!cancelled && !(error instanceof Error && error.name === 'AbortError')) {\n setEnabled(false);\n setReady(false);\n }\n }\n };\n\n void initialize();\n return () => {\n cancelled = true;\n controller.abort();\n unsubscribe();\n };\n }, [\n config.analytics?.enabled,\n config.analytics?.siteKey,\n config.analytics?.trackLocalhost,\n config.analytics?.normalizePath,\n config.apiUrl,\n config.orgId,\n config.stage,\n ]);\n\n return useMemo(\n () => ({ enabled, ready, track, trackPageView }),\n [enabled, ready, track, trackPageView]\n );\n}\n\nexport function useAnalytics(): AnalyticsRuntime {\n return useAxCloudContext().analytics;\n}\n","import { isAxCloudError } from '../core/errors';\nimport type { ContentCollectionType, ContentDetailType } from '../core/types';\nimport type { AxCloudContextValue } from './context';\n\nexport const CONTENT_STALE_TIME_MS = 60_000;\n\nexport function shouldRetryContentRequest(failureCount: number, error: unknown): boolean {\n if (isAxCloudError(error) && error.status >= 400 && error.status < 500) {\n return false;\n }\n return failureCount < 2;\n}\n\nexport function normalizeContentCollectionType(contentType: string): ContentCollectionType {\n switch (contentType.toLowerCase()) {\n case 'news':\n return 'news';\n case 'page':\n case 'pages':\n return 'pages';\n case 'event':\n case 'events':\n return 'events';\n default:\n throw new Error(`Unsupported AxCloud content collection type: ${contentType}`);\n }\n}\n\nexport function normalizeContentDetailType(contentType: string): ContentDetailType {\n switch (contentType.toLowerCase()) {\n case 'news':\n return 'news';\n case 'page':\n case 'pages':\n return 'page';\n case 'event':\n case 'events':\n return 'event';\n default:\n throw new Error(`Unsupported AxCloud content detail type: ${contentType}`);\n }\n}\n\nexport interface ContentAccessState {\n mode: 'public' | 'member' | 'pending';\n enabled: boolean;\n subject: string;\n}\n\nexport function getContentAccessState(\n context: AxCloudContextValue,\n publicOnly: boolean\n): ContentAccessState {\n if (publicOnly) {\n return { mode: 'public', enabled: true, subject: 'anonymous' };\n }\n\n const isLoading = context.isAuthLoading ?? false;\n if (isLoading) {\n return { mode: 'pending', enabled: false, subject: 'auth-loading' };\n }\n\n const hasExplicitAuthState = typeof context.isAuthenticated === 'boolean';\n const isAuthenticated = context.isAuthenticated ?? !context.isPublicMode;\n if (!isAuthenticated) {\n return { mode: 'public', enabled: true, subject: 'anonymous' };\n }\n\n // The built-in provider must never put member content in an identity-agnostic\n // cache while Auth0 has not supplied a subject. The fallback only preserves\n // compatibility with legacy custom contexts that predate explicit auth state.\n if (hasExplicitAuthState && !context.authSubject) {\n return { mode: 'pending', enabled: false, subject: 'auth-subject-pending' };\n }\n const subject = context.authSubject || 'legacy-authenticated-session';\n return { mode: 'member', enabled: Boolean(subject), subject };\n}\n","import { useMemo } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { useAxCloudContext } from '../context'\nimport type {\n ContentItem,\n ContentListResponse,\n ContentQueryOptions,\n} from '../../core/types'\nimport { createContentSlotReader, type ContentSlotReader } from '../../core/contentSlots'\nimport {\n CONTENT_STALE_TIME_MS,\n getContentAccessState,\n normalizeContentCollectionType,\n normalizeContentDetailType,\n shouldRetryContentRequest,\n} from '../contentQueryPolicy'\n\n/**\n * Fetch a published content collection.\n *\n * AxCloud owns editorial data and publication. The consuming application owns\n * layout and rendering. Drafts are intentionally never selectable through\n * this delivery hook.\n */\nexport function useContent<T extends ContentItem = ContentItem>(\n contentType: string,\n options: ContentQueryOptions = {}\n) {\n const context = useAxCloudContext()\n const { client, config, orgId, stage } = context\n const collectionType = normalizeContentCollectionType(contentType)\n\n const {\n publicOnly = false,\n page = 1,\n pageSize = 20,\n search,\n sortBy = collectionType === 'news' ? 'publishedAt' : 'createdAt',\n sortOrder = 'desc',\n tags,\n lang,\n } = options\n\n const access = getContentAccessState(context, publicOnly)\n const deliveryScope = access.mode === 'member' ? 'members' : 'public'\n const params = {\n page,\n pageSize,\n search,\n sort: sortBy,\n order: sortOrder,\n tags: tags?.length ? tags.join(',') : undefined,\n lang,\n }\n\n const query = useQuery<ContentListResponse<T>>({\n queryKey: [\n 'axcloud',\n 'content',\n 'collection',\n stage,\n config.apiUrl,\n orgId,\n access.mode,\n access.subject,\n collectionType,\n params,\n ],\n queryFn: () =>\n client.get<ContentListResponse<T>>(\n `/content/${deliveryScope}/${orgId}/${collectionType}`,\n params\n ),\n enabled: access.enabled,\n staleTime: CONTENT_STALE_TIME_MS,\n refetchOnWindowFocus: true,\n retry: shouldRetryContentRequest,\n })\n\n const items = query.data?.items ?? []\n\n return {\n data: items,\n count: query.data?.count ?? items.length,\n total: query.data?.total ?? items.length,\n page: query.data?.page ?? page,\n pageSize: query.data?.pageSize ?? pageSize,\n hasMore: query.data?.hasMore ?? false,\n nextCursor: query.data?.nextCursor,\n isLoading: access.mode === 'pending' || query.isLoading,\n isFetching: query.isFetching,\n isError: query.isError,\n error: query.error,\n refetch: query.refetch,\n }\n}\n\nexport interface ContentItemOptions {\n /** Force public delivery even when the visitor is authenticated. */\n publicOnly?: boolean\n /** Return the requested translation when content has language variants. */\n lang?: string\n}\n\n/** Fetch one published content item by ID or slug. */\nexport function useContentItem<T extends ContentItem = ContentItem>(\n contentType: string,\n idOrSlug: string,\n options: ContentItemOptions = {}\n) {\n const context = useAxCloudContext()\n const { client, config, orgId, stage } = context\n const detailType = normalizeContentDetailType(contentType)\n const { publicOnly = false, lang } = options\n const access = getContentAccessState(context, publicOnly)\n const deliveryScope = access.mode === 'member' ? 'members' : 'public'\n\n const query = useQuery<T>({\n queryKey: [\n 'axcloud',\n 'content',\n 'item',\n stage,\n config.apiUrl,\n orgId,\n access.mode,\n access.subject,\n detailType,\n idOrSlug,\n lang,\n ],\n queryFn: () => {\n const encodedIdOrSlug = encodeURIComponent(idOrSlug)\n const endpoint = `/content/${deliveryScope}/${orgId}/items/${detailType}/${encodedIdOrSlug}`\n return lang ? client.get<T>(endpoint, { lang }) : client.get<T>(endpoint)\n },\n enabled: access.enabled && Boolean(idOrSlug),\n staleTime: CONTENT_STALE_TIME_MS,\n refetchOnWindowFocus: true,\n retry: shouldRetryContentRequest,\n })\n\n return {\n data: query.data ?? null,\n isLoading: access.mode === 'pending' || query.isLoading,\n isFetching: query.isFetching,\n isError: query.isError,\n error: query.error,\n refetch: query.refetch,\n }\n}\n\nexport interface PageContentState<T extends ContentItem = ContentItem> extends ContentSlotReader {\n page: T | null\n data: T | null\n isLoading: boolean\n isFetching: boolean\n isError: boolean\n error: Error | null\n refetch: () => unknown\n}\n\n/**\n * Fetch a website page and expose structured template fields.\n *\n * Use `page.content`/`page.blocks` for article-like rich text pages. Use\n * `text('hero.title')`, `list('benefits.items')`, etc. for designed website\n * templates where the frontend owns layout and AxCloud owns content.\n */\nexport function usePageContent<T extends ContentItem = ContentItem>(\n slug: string,\n options: ContentItemOptions = {}\n): PageContentState<T> {\n const state = useContentItem<T>('page', slug, options)\n const reader = useMemo(() => createContentSlotReader(state.data), [state.data])\n\n return {\n ...state,\n page: state.data,\n ...reader,\n }\n}\n"]}