@axcode/axcloud-sdk 0.1.7-dev.bf490b9 → 0.1.7-dev.cc5cc69
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/README.md +80 -35
- package/dist/index.d.mts +111 -91
- package/dist/index.d.ts +111 -91
- package/dist/index.js +389 -138
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +391 -141
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
1
|
+
import { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo, useLayoutEffect } from 'react';
|
|
2
2
|
import { Auth0Provider, useAuth0 } from '@auth0/auth0-react';
|
|
3
|
-
import {
|
|
3
|
+
import { QueryClientProvider, useQuery, useQueryClient, useMutation, QueryClient } from '@tanstack/react-query';
|
|
4
4
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/core/errors.ts
|
|
@@ -18,7 +18,7 @@ var AxCloudError = class _AxCloudError extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
static fromResponse(status, body) {
|
|
20
20
|
const details = typeof body === "object" ? body : void 0;
|
|
21
|
-
const message = details?.message;
|
|
21
|
+
const message = (typeof details?.message === "string" ? details.message : void 0) || (typeof details?.error === "string" ? details.error : void 0);
|
|
22
22
|
switch (status) {
|
|
23
23
|
case 401:
|
|
24
24
|
return new _AxCloudError(
|
|
@@ -344,7 +344,7 @@ function getContentSlotMap(content) {
|
|
|
344
344
|
for (const block of content?.blocks || []) {
|
|
345
345
|
const slot = getBlockSlot(block);
|
|
346
346
|
if (!slot) continue;
|
|
347
|
-
fields[slot] = blockToSlotValue(block);
|
|
347
|
+
if (!(slot in fields)) fields[slot] = blockToSlotValue(block);
|
|
348
348
|
}
|
|
349
349
|
return fields;
|
|
350
350
|
}
|
|
@@ -353,11 +353,13 @@ function createContentSlotReader(content) {
|
|
|
353
353
|
const value = (key, fallback) => {
|
|
354
354
|
return key in fields ? fields[key] : fallback;
|
|
355
355
|
};
|
|
356
|
+
const unsafeHtml = (key, fallback = "") => stringifySlotValue(value(key, fallback));
|
|
356
357
|
return {
|
|
357
358
|
fields,
|
|
358
359
|
value,
|
|
359
360
|
text: (key, fallback = "") => stringifySlotValue(value(key, fallback)),
|
|
360
|
-
html:
|
|
361
|
+
html: unsafeHtml,
|
|
362
|
+
unsafeHtml,
|
|
361
363
|
list: (key, fallback = []) => slotValueToList(value(key, fallback)),
|
|
362
364
|
image: (key, fallback) => slotValueToImage(value(key, fallback))
|
|
363
365
|
};
|
|
@@ -753,25 +755,74 @@ function useAnalyticsRuntime(config) {
|
|
|
753
755
|
function useAnalytics() {
|
|
754
756
|
return useAxCloudContext().analytics;
|
|
755
757
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}
|
|
758
|
+
|
|
759
|
+
// src/react/auth/auth0Invitation.ts
|
|
760
|
+
var AUTH0_INVITATION_PATTERN = /^[A-Za-z0-9_-]{1,2048}$/;
|
|
761
|
+
function readAuth0InvitationAuthorizationParams(configuredOrganization, search = typeof window === "undefined" ? "" : window.location.search) {
|
|
762
|
+
if (!configuredOrganization || !search) return {};
|
|
763
|
+
const params = new URLSearchParams(search);
|
|
764
|
+
const invitation = params.get("invitation")?.trim();
|
|
765
|
+
const organization = params.get("organization")?.trim();
|
|
766
|
+
if (organization !== configuredOrganization || !invitation || !AUTH0_INVITATION_PATTERN.test(invitation)) {
|
|
767
|
+
return {};
|
|
766
768
|
}
|
|
767
|
-
}
|
|
769
|
+
return { invitation };
|
|
770
|
+
}
|
|
771
|
+
function createDefaultQueryClient() {
|
|
772
|
+
return new QueryClient({
|
|
773
|
+
defaultOptions: {
|
|
774
|
+
queries: {
|
|
775
|
+
staleTime: 1e3 * 60,
|
|
776
|
+
gcTime: 1e3 * 60 * 30,
|
|
777
|
+
retry: (failureCount, error) => {
|
|
778
|
+
if (isAxCloudError(error) && error.status >= 400 && error.status < 500) {
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
return failureCount < 2;
|
|
782
|
+
},
|
|
783
|
+
refetchOnWindowFocus: true
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
var queryClientAxCloudOwners = /* @__PURE__ */ new WeakMap();
|
|
789
|
+
function createQueryClientOwnerSignature(config, subject) {
|
|
790
|
+
return JSON.stringify([
|
|
791
|
+
subject === null ? "public" : "authenticated",
|
|
792
|
+
subject,
|
|
793
|
+
config.orgId,
|
|
794
|
+
config.stage,
|
|
795
|
+
config.apiUrl,
|
|
796
|
+
config.apiKey ?? null,
|
|
797
|
+
config.auth0.domain,
|
|
798
|
+
config.auth0.clientId,
|
|
799
|
+
config.auth0.audience ?? null,
|
|
800
|
+
config.auth0.organization ?? null,
|
|
801
|
+
config.auth0.connection ?? null
|
|
802
|
+
]);
|
|
803
|
+
}
|
|
768
804
|
function AxCloudInnerProvider({
|
|
769
805
|
children,
|
|
770
806
|
config,
|
|
807
|
+
queryClient,
|
|
771
808
|
timeout
|
|
772
809
|
}) {
|
|
773
|
-
const { getAccessTokenSilently, isAuthenticated } = useAuth0();
|
|
810
|
+
const { getAccessTokenSilently, isAuthenticated, isLoading, user } = useAuth0();
|
|
774
811
|
const analytics = useAnalyticsRuntime(config);
|
|
812
|
+
const [, setOwnerGeneration] = useState(0);
|
|
813
|
+
const currentSubject = isLoading ? void 0 : isAuthenticated ? user?.sub : null;
|
|
814
|
+
const currentOwnerSignature = currentSubject === void 0 ? void 0 : createQueryClientOwnerSignature(config, currentSubject);
|
|
815
|
+
const hasKnownOwner = queryClientAxCloudOwners.has(queryClient);
|
|
816
|
+
const ownerNeedsActivation = currentOwnerSignature !== void 0 && (!hasKnownOwner || queryClientAxCloudOwners.get(queryClient) !== currentOwnerSignature);
|
|
817
|
+
const clearContentCache = useCallback(() => {
|
|
818
|
+
queryClient.removeQueries({ queryKey: ["axcloud"] });
|
|
819
|
+
}, [queryClient]);
|
|
820
|
+
useLayoutEffect(() => {
|
|
821
|
+
if (currentOwnerSignature === void 0 || !ownerNeedsActivation) return;
|
|
822
|
+
clearContentCache();
|
|
823
|
+
queryClientAxCloudOwners.set(queryClient, currentOwnerSignature);
|
|
824
|
+
setOwnerGeneration((generation) => generation + 1);
|
|
825
|
+
}, [clearContentCache, currentOwnerSignature, ownerNeedsActivation, queryClient]);
|
|
775
826
|
const tokenGetterRef = useRef(async () => void 0);
|
|
776
827
|
tokenGetterRef.current = isAuthenticated ? async () => {
|
|
777
828
|
try {
|
|
@@ -801,12 +852,17 @@ function AxCloudInnerProvider({
|
|
|
801
852
|
client,
|
|
802
853
|
orgId: config.orgId,
|
|
803
854
|
stage: config.stage,
|
|
804
|
-
isPublicMode:
|
|
855
|
+
isPublicMode: !isAuthenticated,
|
|
856
|
+
isAuthLoading: isLoading,
|
|
857
|
+
isAuthenticated,
|
|
858
|
+
authSubject: isAuthenticated ? user?.sub : void 0,
|
|
859
|
+
clearContentCache,
|
|
805
860
|
analytics
|
|
806
861
|
}),
|
|
807
|
-
[config, client, isAuthenticated, analytics]
|
|
862
|
+
[config, client, isAuthenticated, isLoading, user?.sub, clearContentCache, analytics]
|
|
808
863
|
);
|
|
809
|
-
|
|
864
|
+
const identityReady = currentOwnerSignature !== void 0 && !ownerNeedsActivation;
|
|
865
|
+
return /* @__PURE__ */ jsx(AxCloudContext.Provider, { value: contextValue, children: identityReady ? children : null });
|
|
810
866
|
}
|
|
811
867
|
function AxCloudProvider({
|
|
812
868
|
children,
|
|
@@ -816,9 +872,12 @@ function AxCloudProvider({
|
|
|
816
872
|
apiKey,
|
|
817
873
|
analytics,
|
|
818
874
|
auth0,
|
|
819
|
-
queryClient
|
|
875
|
+
queryClient: providedQueryClient,
|
|
820
876
|
timeout
|
|
821
877
|
}) {
|
|
878
|
+
const [ownedQueryClient] = useState(createDefaultQueryClient);
|
|
879
|
+
const queryClient = providedQueryClient || ownedQueryClient;
|
|
880
|
+
const invitationAuthorizationParams = readAuth0InvitationAuthorizationParams(auth0.organization);
|
|
822
881
|
const config = useMemo(
|
|
823
882
|
() => ({
|
|
824
883
|
orgId,
|
|
@@ -838,14 +897,15 @@ function AxCloudProvider({
|
|
|
838
897
|
authorizationParams: {
|
|
839
898
|
redirect_uri: auth0.redirectUri,
|
|
840
899
|
audience: auth0.audience,
|
|
841
|
-
...auth0.organization ? { organization: auth0.organization } : {}
|
|
900
|
+
...auth0.organization ? { organization: auth0.organization } : {},
|
|
901
|
+
...invitationAuthorizationParams
|
|
842
902
|
},
|
|
843
|
-
children: /* @__PURE__ */ jsx(AxCloudInnerProvider, { config, timeout, children })
|
|
903
|
+
children: /* @__PURE__ */ jsx(AxCloudInnerProvider, { config, queryClient, timeout, children })
|
|
844
904
|
}
|
|
845
905
|
) });
|
|
846
906
|
}
|
|
847
907
|
function useAuth() {
|
|
848
|
-
const { config, client } = useAxCloudContext();
|
|
908
|
+
const { config, client, clearContentCache } = useAxCloudContext();
|
|
849
909
|
const {
|
|
850
910
|
isAuthenticated,
|
|
851
911
|
isLoading,
|
|
@@ -858,13 +918,17 @@ function useAuth() {
|
|
|
858
918
|
} = useAuth0();
|
|
859
919
|
const login = useCallback(
|
|
860
920
|
(options) => {
|
|
921
|
+
const invitationAuthorizationParams = readAuth0InvitationAuthorizationParams(
|
|
922
|
+
config.auth0.organization
|
|
923
|
+
);
|
|
861
924
|
return loginWithRedirect({
|
|
862
925
|
appState: {
|
|
863
926
|
returnTo: options?.returnTo || window.location.pathname
|
|
864
927
|
},
|
|
865
928
|
...config.auth0.organization ? {
|
|
866
929
|
authorizationParams: {
|
|
867
|
-
organization: config.auth0.organization
|
|
930
|
+
organization: config.auth0.organization,
|
|
931
|
+
...invitationAuthorizationParams
|
|
868
932
|
}
|
|
869
933
|
} : {}
|
|
870
934
|
});
|
|
@@ -873,13 +937,14 @@ function useAuth() {
|
|
|
873
937
|
);
|
|
874
938
|
const logout = useCallback(
|
|
875
939
|
(options) => {
|
|
940
|
+
clearContentCache?.();
|
|
876
941
|
return auth0Logout({
|
|
877
942
|
logoutParams: {
|
|
878
943
|
returnTo: options?.returnTo || window.location.origin
|
|
879
944
|
}
|
|
880
945
|
});
|
|
881
946
|
},
|
|
882
|
-
[auth0Logout]
|
|
947
|
+
[auth0Logout, clearContentCache]
|
|
883
948
|
);
|
|
884
949
|
const getAccessToken = useCallback(async () => {
|
|
885
950
|
try {
|
|
@@ -1030,24 +1095,167 @@ function useAuth() {
|
|
|
1030
1095
|
requestPasswordReset
|
|
1031
1096
|
};
|
|
1032
1097
|
}
|
|
1098
|
+
var currentUserQueryKey = (stage, orgId, subject) => ["axcloud", "user", "me", stage, orgId, subject];
|
|
1099
|
+
function asRecord(value) {
|
|
1100
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1101
|
+
}
|
|
1102
|
+
function asString(value) {
|
|
1103
|
+
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
1104
|
+
}
|
|
1105
|
+
function asStringArray(value) {
|
|
1106
|
+
if (!Array.isArray(value)) return [];
|
|
1107
|
+
return Array.from(new Set(value.map(asString).filter((item) => item !== null)));
|
|
1108
|
+
}
|
|
1109
|
+
function normalizeMembershipSections(rawMembership) {
|
|
1110
|
+
const sections = /* @__PURE__ */ new Map();
|
|
1111
|
+
const addSection = (idValue, nameValue, roleValue) => {
|
|
1112
|
+
const id = asString(idValue);
|
|
1113
|
+
if (!id) return;
|
|
1114
|
+
const existing = sections.get(id);
|
|
1115
|
+
sections.set(id, {
|
|
1116
|
+
id,
|
|
1117
|
+
name: asString(nameValue) || existing?.name || id,
|
|
1118
|
+
role: asString(roleValue) || existing?.role || "member"
|
|
1119
|
+
});
|
|
1120
|
+
};
|
|
1121
|
+
const directSections = rawMembership.sections;
|
|
1122
|
+
if (Array.isArray(directSections)) {
|
|
1123
|
+
for (const rawSection of directSections) {
|
|
1124
|
+
if (typeof rawSection === "string") {
|
|
1125
|
+
addSection(rawSection);
|
|
1126
|
+
continue;
|
|
1127
|
+
}
|
|
1128
|
+
const section = asRecord(rawSection);
|
|
1129
|
+
addSection(
|
|
1130
|
+
section.id ?? section.sectionId ?? section.section_id,
|
|
1131
|
+
section.name ?? section.sectionName ?? section.section_name,
|
|
1132
|
+
section.role
|
|
1133
|
+
);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
const sectionMemberships = asRecord(
|
|
1137
|
+
rawMembership.sectionMemberships ?? rawMembership.section_memberships
|
|
1138
|
+
);
|
|
1139
|
+
for (const [sectionId, rawSectionMembership] of Object.entries(sectionMemberships)) {
|
|
1140
|
+
const sectionMembership = asRecord(rawSectionMembership);
|
|
1141
|
+
addSection(
|
|
1142
|
+
sectionId,
|
|
1143
|
+
sectionMembership.name ?? sectionMembership.sectionName ?? sectionMembership.section_name,
|
|
1144
|
+
sectionMembership.role
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
for (const sectionId of asStringArray(rawMembership.sectionIds ?? rawMembership.section_ids)) {
|
|
1148
|
+
addSection(sectionId);
|
|
1149
|
+
}
|
|
1150
|
+
const primarySectionId = asString(rawMembership.sectionId ?? rawMembership.section_id);
|
|
1151
|
+
if (primarySectionId) addSection(primarySectionId);
|
|
1152
|
+
const normalized = Array.from(sections.values());
|
|
1153
|
+
if (!primarySectionId) return normalized;
|
|
1154
|
+
return normalized.sort((left, right) => {
|
|
1155
|
+
if (left.id === primarySectionId) return -1;
|
|
1156
|
+
if (right.id === primarySectionId) return 1;
|
|
1157
|
+
return 0;
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
function normalizeMembership(rawValue) {
|
|
1161
|
+
const raw = asRecord(rawValue);
|
|
1162
|
+
const role = asString(raw.role) || "member";
|
|
1163
|
+
const roles = asStringArray(raw.roles);
|
|
1164
|
+
const sections = normalizeMembershipSections(raw);
|
|
1165
|
+
const sectionId = asString(raw.sectionId ?? raw.section_id) || sections[0]?.id || null;
|
|
1166
|
+
const joinedAt = asString(raw.joinedAt ?? raw.joined_at);
|
|
1167
|
+
return {
|
|
1168
|
+
role,
|
|
1169
|
+
roles: roles.length > 0 ? roles : [role],
|
|
1170
|
+
title: asString(raw.title),
|
|
1171
|
+
status: asString(raw.status),
|
|
1172
|
+
joinedAt,
|
|
1173
|
+
memberSince: asString(raw.memberSince ?? raw.member_since) || joinedAt,
|
|
1174
|
+
sectionId,
|
|
1175
|
+
sectionIds: sections.map((section) => section.id),
|
|
1176
|
+
sections
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
function normalizeCurrentUserResponse(raw, configuredOrgId) {
|
|
1180
|
+
const rawMemberships = asRecord(
|
|
1181
|
+
raw.organizationMemberships ?? raw.organization_memberships
|
|
1182
|
+
);
|
|
1183
|
+
const organizationMemberships = Object.fromEntries(
|
|
1184
|
+
Object.entries(rawMemberships).map(([organizationId2, membership]) => [
|
|
1185
|
+
organizationId2,
|
|
1186
|
+
normalizeMembership(membership)
|
|
1187
|
+
])
|
|
1188
|
+
);
|
|
1189
|
+
const allOrgIds = Array.from(
|
|
1190
|
+
/* @__PURE__ */ new Set([
|
|
1191
|
+
...asStringArray(raw.allOrgIds ?? raw.all_org_ids),
|
|
1192
|
+
...Object.keys(organizationMemberships)
|
|
1193
|
+
])
|
|
1194
|
+
);
|
|
1195
|
+
const effectiveOrganizationId = asString(
|
|
1196
|
+
raw.effectiveOrganizationId ?? raw.effective_org_id
|
|
1197
|
+
);
|
|
1198
|
+
const primaryOrganizationId = asString(
|
|
1199
|
+
raw.organizationId ?? raw.primary_org_id ?? raw.org_id
|
|
1200
|
+
);
|
|
1201
|
+
const organizationId = effectiveOrganizationId || primaryOrganizationId || (organizationMemberships[configuredOrgId] ? configuredOrgId : null) || allOrgIds[0] || configuredOrgId;
|
|
1202
|
+
const configuredMembership = organizationMemberships[configuredOrgId];
|
|
1203
|
+
const firstName = asString(raw.firstName ?? raw.first_name ?? raw.given_name) || "";
|
|
1204
|
+
const lastName = asString(raw.lastName ?? raw.last_name ?? raw.family_name) || "";
|
|
1205
|
+
const email = asString(raw.email) || "";
|
|
1206
|
+
const createdAt = asString(raw.createdAt ?? raw.created_at) || "";
|
|
1207
|
+
const updatedAt = asString(raw.updatedAt ?? raw.updated_at) || createdAt;
|
|
1208
|
+
const role = configuredMembership?.role || asString(raw.role) || "member";
|
|
1209
|
+
const sectionId = configuredMembership?.sectionId || asString(raw.sectionId ?? raw.section_id);
|
|
1210
|
+
const permissions = asStringArray(raw.permissions ?? raw.effective_permissions);
|
|
1211
|
+
const metadata = asRecord(raw.metadata);
|
|
1212
|
+
return {
|
|
1213
|
+
id: asString(raw.id ?? raw.userId ?? raw.user_id ?? raw.sub) || "",
|
|
1214
|
+
email,
|
|
1215
|
+
name: asString(raw.name) || [firstName, lastName].filter(Boolean).join(" ") || email,
|
|
1216
|
+
firstName,
|
|
1217
|
+
lastName,
|
|
1218
|
+
title: configuredMembership?.title ?? asString(raw.title),
|
|
1219
|
+
phone: asString(raw.phone ?? raw.phoneNumber ?? raw.phone_number),
|
|
1220
|
+
address: asString(raw.address ?? raw.location),
|
|
1221
|
+
avatar: asString(raw.avatar ?? raw.avatarUrl ?? raw.avatar_url ?? raw.picture) || void 0,
|
|
1222
|
+
organizationId,
|
|
1223
|
+
...sectionId ? { sectionId } : {},
|
|
1224
|
+
role,
|
|
1225
|
+
permissions,
|
|
1226
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {},
|
|
1227
|
+
createdAt,
|
|
1228
|
+
updatedAt,
|
|
1229
|
+
allOrgIds,
|
|
1230
|
+
organizationMemberships,
|
|
1231
|
+
effectiveOrganizationId,
|
|
1232
|
+
isSuperAdmin: raw.isSuperAdmin === true || raw.is_super_admin === true || asString(raw.global_role) === "super_admin" || role === "super_admin"
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1033
1235
|
function useUser() {
|
|
1034
1236
|
const { isAuthenticated, isLoading: isAuthLoading, user: auth0User } = useAuth0();
|
|
1035
1237
|
const { client, stage, orgId } = useAxCloudContext();
|
|
1238
|
+
const queryKey = currentUserQueryKey(stage, orgId, auth0User?.sub);
|
|
1036
1239
|
const query = useQuery({
|
|
1037
|
-
queryKey
|
|
1240
|
+
queryKey,
|
|
1038
1241
|
queryFn: async () => {
|
|
1039
|
-
|
|
1242
|
+
const response = await client.get("/api/users/me");
|
|
1243
|
+
return normalizeCurrentUserResponse(response, orgId);
|
|
1040
1244
|
},
|
|
1041
1245
|
enabled: isAuthenticated && !isAuthLoading,
|
|
1042
1246
|
staleTime: 1e3 * 60 * 5
|
|
1043
1247
|
// 5 minutes
|
|
1044
1248
|
});
|
|
1045
1249
|
const userData = query.data;
|
|
1046
|
-
const userOrgIds = userData?.
|
|
1250
|
+
const userOrgIds = userData?.allOrgIds ?? [];
|
|
1047
1251
|
const isSuperAdmin = userData?.isSuperAdmin === true;
|
|
1048
|
-
const
|
|
1049
|
-
const
|
|
1252
|
+
const orgMembership = userData?.organizationMemberships?.[orgId];
|
|
1253
|
+
const hasOrgAccess = userOrgIds.includes(orgId) && orgMembership?.status?.trim().toLowerCase() === "active";
|
|
1050
1254
|
const roleInOrg = orgMembership?.role ?? null;
|
|
1255
|
+
const sectionId = orgMembership?.sectionId ?? userData?.sectionId ?? null;
|
|
1256
|
+
const sections = orgMembership?.sections?.length ? orgMembership.sections : sectionId ? [{ id: sectionId, name: sectionId, role: roleInOrg ?? "member" }] : [];
|
|
1257
|
+
const section = sections.find((item) => item.id === sectionId) ?? sections[0] ?? null;
|
|
1258
|
+
const memberSince = orgMembership?.memberSince ?? null;
|
|
1051
1259
|
return {
|
|
1052
1260
|
user: query.data ?? null,
|
|
1053
1261
|
isLoading: isAuthLoading || query.isLoading,
|
|
@@ -1057,15 +1265,35 @@ function useUser() {
|
|
|
1057
1265
|
// Organization access
|
|
1058
1266
|
hasOrgAccess,
|
|
1059
1267
|
roleInOrg,
|
|
1268
|
+
organizationMembership: orgMembership ?? null,
|
|
1269
|
+
title: orgMembership?.title ?? query.data?.title ?? null,
|
|
1270
|
+
section,
|
|
1271
|
+
sections,
|
|
1272
|
+
sectionIds: orgMembership?.sectionIds?.length ? orgMembership.sectionIds : sectionId ? [sectionId] : [],
|
|
1273
|
+
joinedAt: orgMembership?.joinedAt ?? null,
|
|
1274
|
+
memberSince,
|
|
1060
1275
|
// Convenience properties
|
|
1061
1276
|
isAuthenticated,
|
|
1062
|
-
role: query.data?.role ?? null,
|
|
1277
|
+
role: roleInOrg ?? query.data?.role ?? null,
|
|
1063
1278
|
organizationId: query.data?.organizationId ?? null,
|
|
1064
|
-
sectionId
|
|
1279
|
+
sectionId,
|
|
1065
1280
|
permissions: query.data?.permissions ?? [],
|
|
1066
1281
|
isSuperAdmin
|
|
1067
1282
|
};
|
|
1068
1283
|
}
|
|
1284
|
+
function useUpdateMyProfile() {
|
|
1285
|
+
const { client, stage } = useAxCloudContext();
|
|
1286
|
+
const queryClient = useQueryClient();
|
|
1287
|
+
return useMutation({
|
|
1288
|
+
mutationFn: (updates) => client.patch("/api/users/me/profile", updates),
|
|
1289
|
+
onSuccess: async () => {
|
|
1290
|
+
await queryClient.invalidateQueries({
|
|
1291
|
+
queryKey: ["axcloud", "user", "me", stage],
|
|
1292
|
+
exact: false
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1069
1297
|
function useOrg() {
|
|
1070
1298
|
const { client, orgId, stage, isPublicMode } = useAxCloudContext();
|
|
1071
1299
|
const usePublicEndpoint = isPublicMode;
|
|
@@ -1112,152 +1340,169 @@ function useOrg() {
|
|
|
1112
1340
|
modules
|
|
1113
1341
|
};
|
|
1114
1342
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
"
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
status,
|
|
1152
|
-
visibility,
|
|
1153
|
-
sectionId,
|
|
1154
|
-
search,
|
|
1155
|
-
sortBy,
|
|
1156
|
-
sortOrder,
|
|
1157
|
-
lang
|
|
1158
|
-
});
|
|
1159
|
-
},
|
|
1160
|
-
staleTime: 1e3 * 60 * 5
|
|
1161
|
-
// 5 minutes
|
|
1162
|
-
});
|
|
1163
|
-
return {
|
|
1164
|
-
data: query.data?.items ?? [],
|
|
1165
|
-
total: query.data?.total ?? 0,
|
|
1166
|
-
hasMore: query.data?.hasMore ?? false,
|
|
1167
|
-
isLoading: query.isLoading,
|
|
1168
|
-
isError: query.isError,
|
|
1169
|
-
error: query.error,
|
|
1170
|
-
refetch: query.refetch
|
|
1171
|
-
};
|
|
1343
|
+
|
|
1344
|
+
// src/react/contentQueryPolicy.ts
|
|
1345
|
+
var CONTENT_STALE_TIME_MS = 6e4;
|
|
1346
|
+
function shouldRetryContentRequest(failureCount, error) {
|
|
1347
|
+
if (isAxCloudError(error) && error.status >= 400 && error.status < 500) {
|
|
1348
|
+
return false;
|
|
1349
|
+
}
|
|
1350
|
+
return failureCount < 2;
|
|
1351
|
+
}
|
|
1352
|
+
function normalizeContentCollectionType(contentType) {
|
|
1353
|
+
switch (contentType.toLowerCase()) {
|
|
1354
|
+
case "news":
|
|
1355
|
+
return "news";
|
|
1356
|
+
case "page":
|
|
1357
|
+
case "pages":
|
|
1358
|
+
return "pages";
|
|
1359
|
+
case "event":
|
|
1360
|
+
case "events":
|
|
1361
|
+
return "events";
|
|
1362
|
+
default:
|
|
1363
|
+
throw new Error(`Unsupported AxCloud content collection type: ${contentType}`);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
function normalizeContentDetailType(contentType) {
|
|
1367
|
+
switch (contentType.toLowerCase()) {
|
|
1368
|
+
case "news":
|
|
1369
|
+
return "news";
|
|
1370
|
+
case "page":
|
|
1371
|
+
case "pages":
|
|
1372
|
+
return "page";
|
|
1373
|
+
case "event":
|
|
1374
|
+
case "events":
|
|
1375
|
+
return "event";
|
|
1376
|
+
default:
|
|
1377
|
+
throw new Error(`Unsupported AxCloud content detail type: ${contentType}`);
|
|
1378
|
+
}
|
|
1172
1379
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1380
|
+
function getContentAccessState(context, publicOnly) {
|
|
1381
|
+
if (publicOnly) {
|
|
1382
|
+
return { mode: "public", enabled: true, subject: "anonymous" };
|
|
1383
|
+
}
|
|
1384
|
+
const isLoading = context.isAuthLoading ?? false;
|
|
1385
|
+
if (isLoading) {
|
|
1386
|
+
return { mode: "pending", enabled: false, subject: "auth-loading" };
|
|
1387
|
+
}
|
|
1388
|
+
const hasExplicitAuthState = typeof context.isAuthenticated === "boolean";
|
|
1389
|
+
const isAuthenticated = context.isAuthenticated ?? !context.isPublicMode;
|
|
1390
|
+
if (!isAuthenticated) {
|
|
1391
|
+
return { mode: "public", enabled: true, subject: "anonymous" };
|
|
1392
|
+
}
|
|
1393
|
+
if (hasExplicitAuthState && !context.authSubject) {
|
|
1394
|
+
return { mode: "pending", enabled: false, subject: "auth-subject-pending" };
|
|
1395
|
+
}
|
|
1396
|
+
const subject = context.authSubject || "legacy-authenticated-session";
|
|
1397
|
+
return { mode: "member", enabled: Boolean(subject), subject };
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
// src/react/hooks/useContent.ts
|
|
1175
1401
|
function useContent(contentType, options = {}) {
|
|
1176
|
-
const
|
|
1402
|
+
const context = useAxCloudContext();
|
|
1403
|
+
const { client, config, orgId, stage } = context;
|
|
1404
|
+
const collectionType = normalizeContentCollectionType(contentType);
|
|
1177
1405
|
const {
|
|
1178
1406
|
publicOnly = false,
|
|
1179
1407
|
page = 1,
|
|
1180
1408
|
pageSize = 20,
|
|
1181
|
-
status = "published",
|
|
1182
|
-
visibility,
|
|
1183
|
-
sectionId,
|
|
1184
1409
|
search,
|
|
1185
|
-
sortBy = "createdAt",
|
|
1410
|
+
sortBy = collectionType === "news" ? "publishedAt" : "createdAt",
|
|
1186
1411
|
sortOrder = "desc",
|
|
1412
|
+
tags,
|
|
1187
1413
|
lang
|
|
1188
1414
|
} = options;
|
|
1415
|
+
const access = getContentAccessState(context, publicOnly);
|
|
1416
|
+
const deliveryScope = access.mode === "member" ? "members" : "public";
|
|
1417
|
+
const params = {
|
|
1418
|
+
page,
|
|
1419
|
+
pageSize,
|
|
1420
|
+
search,
|
|
1421
|
+
sort: sortBy,
|
|
1422
|
+
order: sortOrder,
|
|
1423
|
+
tags: tags?.length ? tags.join(",") : void 0,
|
|
1424
|
+
lang
|
|
1425
|
+
};
|
|
1189
1426
|
const query = useQuery({
|
|
1190
1427
|
queryKey: [
|
|
1191
1428
|
"axcloud",
|
|
1192
1429
|
"content",
|
|
1430
|
+
"collection",
|
|
1431
|
+
stage,
|
|
1432
|
+
config.apiUrl,
|
|
1193
1433
|
orgId,
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
pageSize,
|
|
1199
|
-
status,
|
|
1200
|
-
visibility,
|
|
1201
|
-
sectionId,
|
|
1202
|
-
search,
|
|
1203
|
-
sortBy,
|
|
1204
|
-
sortOrder,
|
|
1205
|
-
lang
|
|
1434
|
+
access.mode,
|
|
1435
|
+
access.subject,
|
|
1436
|
+
collectionType,
|
|
1437
|
+
params
|
|
1206
1438
|
],
|
|
1207
|
-
queryFn:
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
sectionId,
|
|
1216
|
-
search,
|
|
1217
|
-
sortBy,
|
|
1218
|
-
sortOrder,
|
|
1219
|
-
lang
|
|
1220
|
-
});
|
|
1221
|
-
},
|
|
1222
|
-
staleTime: 1e3 * 60 * 5
|
|
1223
|
-
// 5 minutes
|
|
1439
|
+
queryFn: () => client.get(
|
|
1440
|
+
`/content/${deliveryScope}/${orgId}/${collectionType}`,
|
|
1441
|
+
params
|
|
1442
|
+
),
|
|
1443
|
+
enabled: access.enabled,
|
|
1444
|
+
staleTime: CONTENT_STALE_TIME_MS,
|
|
1445
|
+
refetchOnWindowFocus: true,
|
|
1446
|
+
retry: shouldRetryContentRequest
|
|
1224
1447
|
});
|
|
1448
|
+
const items = query.data?.items ?? [];
|
|
1225
1449
|
return {
|
|
1226
|
-
data:
|
|
1227
|
-
|
|
1450
|
+
data: items,
|
|
1451
|
+
count: query.data?.count ?? items.length,
|
|
1452
|
+
total: query.data?.total ?? items.length,
|
|
1453
|
+
page: query.data?.page ?? page,
|
|
1454
|
+
pageSize: query.data?.pageSize ?? pageSize,
|
|
1228
1455
|
hasMore: query.data?.hasMore ?? false,
|
|
1229
|
-
|
|
1456
|
+
nextCursor: query.data?.nextCursor,
|
|
1457
|
+
isLoading: access.mode === "pending" || query.isLoading,
|
|
1458
|
+
isFetching: query.isFetching,
|
|
1230
1459
|
isError: query.isError,
|
|
1231
1460
|
error: query.error,
|
|
1232
1461
|
refetch: query.refetch
|
|
1233
1462
|
};
|
|
1234
1463
|
}
|
|
1235
1464
|
function useContentItem(contentType, idOrSlug, options = {}) {
|
|
1236
|
-
const
|
|
1465
|
+
const context = useAxCloudContext();
|
|
1466
|
+
const { client, config, orgId, stage } = context;
|
|
1467
|
+
const detailType = normalizeContentDetailType(contentType);
|
|
1237
1468
|
const { publicOnly = false, lang } = options;
|
|
1238
|
-
const
|
|
1469
|
+
const access = getContentAccessState(context, publicOnly);
|
|
1470
|
+
const deliveryScope = access.mode === "member" ? "members" : "public";
|
|
1239
1471
|
const query = useQuery({
|
|
1240
|
-
queryKey: [
|
|
1241
|
-
|
|
1242
|
-
|
|
1472
|
+
queryKey: [
|
|
1473
|
+
"axcloud",
|
|
1474
|
+
"content",
|
|
1475
|
+
"item",
|
|
1476
|
+
stage,
|
|
1477
|
+
config.apiUrl,
|
|
1478
|
+
orgId,
|
|
1479
|
+
access.mode,
|
|
1480
|
+
access.subject,
|
|
1481
|
+
detailType,
|
|
1482
|
+
idOrSlug,
|
|
1483
|
+
lang
|
|
1484
|
+
],
|
|
1485
|
+
queryFn: () => {
|
|
1243
1486
|
const encodedIdOrSlug = encodeURIComponent(idOrSlug);
|
|
1244
|
-
const endpoint =
|
|
1487
|
+
const endpoint = `/content/${deliveryScope}/${orgId}/items/${detailType}/${encodedIdOrSlug}`;
|
|
1245
1488
|
return lang ? client.get(endpoint, { lang }) : client.get(endpoint);
|
|
1246
1489
|
},
|
|
1247
|
-
enabled:
|
|
1248
|
-
staleTime:
|
|
1249
|
-
|
|
1490
|
+
enabled: access.enabled && Boolean(idOrSlug),
|
|
1491
|
+
staleTime: CONTENT_STALE_TIME_MS,
|
|
1492
|
+
refetchOnWindowFocus: true,
|
|
1493
|
+
retry: shouldRetryContentRequest
|
|
1250
1494
|
});
|
|
1251
1495
|
return {
|
|
1252
1496
|
data: query.data ?? null,
|
|
1253
|
-
isLoading: query.isLoading,
|
|
1497
|
+
isLoading: access.mode === "pending" || query.isLoading,
|
|
1498
|
+
isFetching: query.isFetching,
|
|
1254
1499
|
isError: query.isError,
|
|
1255
1500
|
error: query.error,
|
|
1256
1501
|
refetch: query.refetch
|
|
1257
1502
|
};
|
|
1258
1503
|
}
|
|
1259
1504
|
function usePageContent(slug, options = {}) {
|
|
1260
|
-
const state = useContentItem("
|
|
1505
|
+
const state = useContentItem("page", slug, options);
|
|
1261
1506
|
const reader = useMemo(() => createContentSlotReader(state.data), [state.data]);
|
|
1262
1507
|
return {
|
|
1263
1508
|
...state,
|
|
@@ -1265,6 +1510,11 @@ function usePageContent(slug, options = {}) {
|
|
|
1265
1510
|
...reader
|
|
1266
1511
|
};
|
|
1267
1512
|
}
|
|
1513
|
+
|
|
1514
|
+
// src/react/hooks/useNews.ts
|
|
1515
|
+
function useNews(options = {}) {
|
|
1516
|
+
return useContent("news", options);
|
|
1517
|
+
}
|
|
1268
1518
|
function useMySection(options = {}) {
|
|
1269
1519
|
const { includeMembers = true } = options;
|
|
1270
1520
|
const { isAuthenticated } = useAuth0();
|
|
@@ -2093,6 +2343,6 @@ function LinkedAccountsList({
|
|
|
2093
2343
|
] });
|
|
2094
2344
|
}
|
|
2095
2345
|
|
|
2096
|
-
export { AxCloudClient, AxCloudError, AxCloudProvider, LinkedAccountsList, LoginButton, LogoutButton, ModuleGate, ProtectedRoute, castVote, castVoteWithCode, checkEligibility, checkVotingCode, createClient, createContentSlotReader, createFormHelper, fetchAnalyticsPublicConfig, getBallot, getClient, getContentSlotMap, getVotingReceipt, isAllowedAnalyticsEvent, isAxCloudError, isLocalAnalyticsHostname, sanitizeAnalyticsEventData, sanitizeAnalyticsPath, submitForm, useAnalytics, useAnalyticsRuntime, useAuth, useAvatar, useAxCloudContext, useBarnsportActivities, useBarnsportActivity, useBarnsportMunicipalities, useBarnsportSitemap, useBarnsportSport, useBarnsportSports, useBranding, useCodeBallot, useContent, useContentItem, useDocumentDownload, useDocuments, useFormStats, useForms, useLinkedAccounts, useLogo, useMedia, useMediaList, useMemberDocumentDownload, useMemberDocumentFolders, useMemberDocuments, useModuleAccess, useMySection, useNews, useOrg, usePageContent, useSections, useSubmitBarnsportInterest, useUpdateFormSubmission, useUser, userHasAllPermissions, userHasAnyPermission, userHasPermission };
|
|
2346
|
+
export { AxCloudClient, AxCloudError, AxCloudProvider, LinkedAccountsList, LoginButton, LogoutButton, ModuleGate, ProtectedRoute, castVote, castVoteWithCode, checkEligibility, checkVotingCode, createClient, createContentSlotReader, createFormHelper, fetchAnalyticsPublicConfig, getBallot, getClient, getContentSlotMap, getVotingReceipt, isAllowedAnalyticsEvent, isAxCloudError, isLocalAnalyticsHostname, sanitizeAnalyticsEventData, sanitizeAnalyticsPath, submitForm, useAnalytics, useAnalyticsRuntime, useAuth, useAvatar, useAxCloudContext, useBarnsportActivities, useBarnsportActivity, useBarnsportMunicipalities, useBarnsportSitemap, useBarnsportSport, useBarnsportSports, useBranding, useCodeBallot, useContent, useContentItem, useDocumentDownload, useDocuments, useFormStats, useForms, useLinkedAccounts, useLogo, useMedia, useMediaList, useMemberDocumentDownload, useMemberDocumentFolders, useMemberDocuments, useModuleAccess, useMySection, useNews, useOrg, usePageContent, useSections, useSubmitBarnsportInterest, useUpdateFormSubmission, useUpdateMyProfile, useUser, userHasAllPermissions, userHasAnyPermission, userHasPermission };
|
|
2097
2347
|
//# sourceMappingURL=index.mjs.map
|
|
2098
2348
|
//# sourceMappingURL=index.mjs.map
|