@elevasis/ui 1.2.1 → 1.3.1

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 (59) hide show
  1. package/dist/CoreAuthKitInner-3J4RVQO6.js +43 -0
  2. package/dist/api/index.d.ts +32 -18
  3. package/dist/api/index.js +4 -2
  4. package/dist/auth/context.d.ts +23 -5
  5. package/dist/auth/index.d.ts +119 -30
  6. package/dist/auth/index.js +6 -3
  7. package/dist/chunk-2JBWPFHF.js +108 -0
  8. package/dist/chunk-4VGWQ5AN.js +91 -0
  9. package/dist/chunk-72HOBFMP.js +87 -0
  10. package/dist/{chunk-WNWKOCGJ.js → chunk-A3MCANC6.js} +296 -2
  11. package/dist/{chunk-JKERRYVS.js → chunk-BLO4SISK.js} +7 -3
  12. package/dist/chunk-DD3CCMCZ.js +15 -0
  13. package/dist/chunk-FWZJH3TL.js +13 -0
  14. package/dist/{chunk-GEFB5YIR.js → chunk-JBFFCZI4.js} +1 -1
  15. package/dist/chunk-JGJSZ3UE.js +47 -0
  16. package/dist/{chunk-7AI5ZYJ4.js → chunk-JVAZHVNV.js} +2 -94
  17. package/dist/{chunk-ZGHDPDTF.js → chunk-JYSYHVLU.js} +3 -3
  18. package/dist/{chunk-5UWFGBFM.js → chunk-L2CM2CUA.js} +16 -4
  19. package/dist/chunk-NEK6JKPW.js +75 -0
  20. package/dist/{chunk-J3FALDQE.js → chunk-NXHL23JW.js} +7 -13
  21. package/dist/{chunk-OUHGHTE7.js → chunk-O3PY6B6E.js} +3 -2
  22. package/dist/{chunk-YULUKCS6.js → chunk-PVVQTENF.js} +1 -1
  23. package/dist/chunk-TIRMFDM4.js +33 -0
  24. package/dist/{chunk-PYL4XW6H.js → chunk-TMFCNFLW.js} +1 -1
  25. package/dist/{chunk-S66I2PYB.js → chunk-TN3PU2WK.js} +1 -1
  26. package/dist/chunk-TYV5NJV2.js +1 -0
  27. package/dist/{chunk-B64YDSAY.js → chunk-TZPAA4RC.js} +54 -97
  28. package/dist/chunk-UMXDDEAG.js +148 -0
  29. package/dist/chunk-XLV6LYN2.js +157 -0
  30. package/dist/components/command-queue/index.js +6 -4
  31. package/dist/components/index.js +9 -7
  32. package/dist/components/notifications/index.js +4 -3
  33. package/dist/display/index.js +3 -2
  34. package/dist/hooks/index.d.ts +2630 -3
  35. package/dist/hooks/index.js +9 -5
  36. package/dist/hooks/published.d.ts +2630 -3
  37. package/dist/hooks/published.js +7 -3
  38. package/dist/index.d.ts +759 -164
  39. package/dist/index.js +24 -18
  40. package/dist/initialization/index.d.ts +49 -1
  41. package/dist/initialization/index.js +5 -2
  42. package/dist/organization/index.d.ts +61 -2
  43. package/dist/organization/index.js +5 -2
  44. package/dist/profile/index.d.ts +30 -2
  45. package/dist/profile/index.js +2 -1
  46. package/dist/provider/index.d.ts +116 -43
  47. package/dist/provider/index.js +10 -6
  48. package/dist/provider/published.d.ts +88 -28
  49. package/dist/provider/published.js +9 -4
  50. package/dist/supabase/index.js +2 -47
  51. package/dist/utils/index.js +2 -1
  52. package/package.json +15 -2
  53. package/dist/CoreAuthKitInner-KM72EYJS.js +0 -19
  54. package/dist/chunk-GDV44UWF.js +0 -138
  55. package/dist/chunk-HBRMWW6V.js +0 -43
  56. package/dist/chunk-NIAVTSMB.js +0 -21
  57. package/dist/chunk-QSVZP2NU.js +0 -214
  58. package/dist/chunk-ZQVPUAGR.js +0 -89
  59. /package/dist/{chunk-Q47SPRY7.js → chunk-RNP5R5I3.js} +0 -0
@@ -1,7 +1,11 @@
1
- import { UuidSchema, ResourceTypeSchema, NonEmptyStringSchema, OriginResourceTypeSchema } from './chunk-JKERRYVS.js';
1
+ import { useSupabase } from './chunk-JGJSZ3UE.js';
2
+ import { UuidSchema, ResourceTypeSchema, NonEmptyStringSchema, OriginResourceTypeSchema } from './chunk-BLO4SISK.js';
3
+ import { useNotificationAdapter } from './chunk-TIRMFDM4.js';
4
+ import { useStableAccessToken } from './chunk-FWZJH3TL.js';
2
5
  import { useElevasisServices } from './chunk-KA7LO7U5.js';
3
6
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
4
7
  import { z } from 'zod';
8
+ import { useCallback, useState, useEffect, useMemo, useId, useRef } from 'react';
5
9
 
6
10
  // src/hooks/executions/queryKeys.ts
7
11
  var executionsKeys = {
@@ -658,6 +662,43 @@ function useExecutionHealth({ timeRange }) {
658
662
  // 30s monitoring stale time
659
663
  });
660
664
  }
665
+ function useErrorNotification() {
666
+ const adapter = useNotificationAdapter();
667
+ return useCallback(
668
+ (error) => {
669
+ adapter.apiError(error);
670
+ },
671
+ [adapter]
672
+ );
673
+ }
674
+ function useSuccessNotification() {
675
+ const adapter = useNotificationAdapter();
676
+ return useCallback((title, message) => adapter.success(title, message), [adapter]);
677
+ }
678
+ function useWarningNotification() {
679
+ const adapter = useNotificationAdapter();
680
+ return useCallback((title, message) => adapter.warning(title, message), [adapter]);
681
+ }
682
+ function useBatchDelete(tableName, invalidateQueryKeys) {
683
+ const supabase = useSupabase();
684
+ const queryClient = useQueryClient();
685
+ const adapter = useNotificationAdapter();
686
+ return useMutation({
687
+ mutationFn: async (ids) => {
688
+ if (ids.length === 0) return;
689
+ const { error } = await supabase.from(tableName).delete().in("id", ids);
690
+ if (error) throw error;
691
+ },
692
+ onSuccess: () => {
693
+ for (const key of invalidateQueryKeys) {
694
+ queryClient.invalidateQueries({ queryKey: key });
695
+ }
696
+ },
697
+ onError: (err) => {
698
+ adapter.apiError(err);
699
+ }
700
+ });
701
+ }
661
702
 
662
703
  // src/hooks/observability/queryKeys.ts
663
704
  var observabilityKeys = {
@@ -1063,5 +1104,258 @@ function useDeleteSchedule() {
1063
1104
  }
1064
1105
  });
1065
1106
  }
1107
+ function usePaginationState(pageSize, resetDeps, total) {
1108
+ const [page, setPage] = useState(1);
1109
+ useEffect(() => {
1110
+ if (resetDeps) {
1111
+ setPage(1);
1112
+ }
1113
+ }, resetDeps ?? []);
1114
+ useEffect(() => {
1115
+ if (total === void 0) return;
1116
+ const lastPage = Math.max(1, Math.ceil(total / pageSize));
1117
+ if (page > lastPage) {
1118
+ setPage(lastPage);
1119
+ }
1120
+ }, [total, pageSize]);
1121
+ return useMemo(
1122
+ () => ({
1123
+ page,
1124
+ setPage,
1125
+ offset: (page - 1) * pageSize,
1126
+ totalPages: (total2) => Math.ceil(total2 / pageSize)
1127
+ }),
1128
+ [page, pageSize]
1129
+ );
1130
+ }
1131
+ function useTableSelection(items, allItems) {
1132
+ const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
1133
+ const pageIds = useMemo(() => new Set(items.map((i) => i.id)), [items]);
1134
+ useEffect(() => {
1135
+ setSelectedIds((prev) => {
1136
+ const validIds = allItems ? new Set(allItems.map((i) => i.id)) : pageIds;
1137
+ const next = new Set([...prev].filter((id) => validIds.has(id)));
1138
+ return next.size === prev.size ? prev : next;
1139
+ });
1140
+ }, [allItems, pageIds]);
1141
+ const toggle = useCallback((id) => {
1142
+ setSelectedIds((prev) => {
1143
+ const next = new Set(prev);
1144
+ if (next.has(id)) next.delete(id);
1145
+ else next.add(id);
1146
+ return next;
1147
+ });
1148
+ }, []);
1149
+ const togglePage = useCallback(() => {
1150
+ setSelectedIds((prev) => {
1151
+ const allPageSelected = items.every((i) => prev.has(i.id));
1152
+ const next = new Set(prev);
1153
+ if (allPageSelected) {
1154
+ for (const item of items) next.delete(item.id);
1155
+ } else {
1156
+ for (const item of items) next.add(item.id);
1157
+ }
1158
+ return next;
1159
+ });
1160
+ }, [items]);
1161
+ const clear = useCallback(() => setSelectedIds(/* @__PURE__ */ new Set()), []);
1162
+ const isPageAllSelected = items.length > 0 && items.every((i) => selectedIds.has(i.id));
1163
+ const isPagePartiallySelected = !isPageAllSelected && items.some((i) => selectedIds.has(i.id));
1164
+ return {
1165
+ selectedIds,
1166
+ toggle,
1167
+ togglePage,
1168
+ clear,
1169
+ isPageAllSelected,
1170
+ isPagePartiallySelected,
1171
+ selectedCount: selectedIds.size,
1172
+ isSelected: (id) => selectedIds.has(id)
1173
+ };
1174
+ }
1175
+ function useTableSort(defaultColumn, defaultDirection = "desc") {
1176
+ const [sort, setSort] = useState({ column: defaultColumn, direction: defaultDirection });
1177
+ const toggleSort = useCallback((column) => {
1178
+ setSort((prev) => {
1179
+ if (prev.column === column) {
1180
+ return { column, direction: prev.direction === "asc" ? "desc" : "asc" };
1181
+ }
1182
+ return { column, direction: "desc" };
1183
+ });
1184
+ }, []);
1185
+ return { sort, toggleSort };
1186
+ }
1187
+ function sortData(data, sort, accessors) {
1188
+ const accessor = accessors[sort.column];
1189
+ if (!accessor) return data;
1190
+ return [...data].sort((a, b) => {
1191
+ const aVal = accessor(a);
1192
+ const bVal = accessor(b);
1193
+ if (aVal == null && bVal == null) return 0;
1194
+ if (aVal == null) return 1;
1195
+ if (bVal == null) return -1;
1196
+ let comparison = 0;
1197
+ if (typeof aVal === "string" && typeof bVal === "string") {
1198
+ comparison = aVal.localeCompare(bVal);
1199
+ } else if (typeof aVal === "number" && typeof bVal === "number") {
1200
+ comparison = aVal - bVal;
1201
+ } else {
1202
+ comparison = String(aVal).localeCompare(String(bVal));
1203
+ }
1204
+ return sort.direction === "asc" ? comparison : -comparison;
1205
+ });
1206
+ }
1207
+ function useSortedData(data, defaultColumn, accessors, defaultDirection = "desc") {
1208
+ const { sort, toggleSort } = useTableSort(defaultColumn, defaultDirection);
1209
+ const sorted = useMemo(() => sortData(data, sort, accessors), [data, sort, accessors]);
1210
+ return { sorted, sort, toggleSort };
1211
+ }
1212
+ function createUseFeatureAccess({
1213
+ useInitialization,
1214
+ useOrganization,
1215
+ optInFeatures = [],
1216
+ getCoursesByGroup = () => []
1217
+ }) {
1218
+ return function useFeatureAccess() {
1219
+ const { profile, organizationReady } = useInitialization();
1220
+ const { currentMembership } = useOrganization();
1221
+ const { orgConfig, membershipConfig } = useMemo(() => {
1222
+ const organizationConfig = currentMembership?.organization?.config;
1223
+ const memberConfig = currentMembership?.config;
1224
+ return { orgConfig: organizationConfig, membershipConfig: memberConfig };
1225
+ }, [currentMembership]);
1226
+ const userConfig = profile?.config;
1227
+ const checkFeature = useCallback(
1228
+ (featureKey) => {
1229
+ const key = featureKey;
1230
+ const orgValue = orgConfig?.features?.[key];
1231
+ if (!profile?.is_platform_admin) {
1232
+ const membershipValue = membershipConfig?.features?.[key];
1233
+ if (membershipValue === false) return { allowed: false, restrictedBy: "membership" };
1234
+ if (membershipValue === true) return { allowed: true, restrictedBy: null };
1235
+ }
1236
+ if (optInFeatures.includes(featureKey)) {
1237
+ return orgValue === true ? { allowed: true, restrictedBy: null } : { allowed: false, restrictedBy: "org" };
1238
+ }
1239
+ return orgValue === false ? { allowed: false, restrictedBy: "org" } : { allowed: true, restrictedBy: null };
1240
+ },
1241
+ [profile?.is_platform_admin, membershipConfig, orgConfig]
1242
+ );
1243
+ const hasFeature = useCallback((featureKey) => checkFeature(featureKey).allowed, [checkFeature]);
1244
+ const hasTrainingAccess = useCallback(() => {
1245
+ if (profile?.is_platform_admin) return true;
1246
+ return userConfig?.training?.enabled ?? true;
1247
+ }, [profile?.is_platform_admin, userConfig?.training?.enabled]);
1248
+ const getAllowedCourses = useCallback(() => {
1249
+ if (userConfig?.training?.allowed_courses?.length) {
1250
+ return userConfig.training.allowed_courses;
1251
+ }
1252
+ return null;
1253
+ }, [userConfig?.training?.allowed_courses]);
1254
+ const getResolvedCourseAccess = useCallback(() => {
1255
+ if (profile?.is_platform_admin) return null;
1256
+ const orgGroups = orgConfig?.training?.allowed_course_groups ?? [];
1257
+ const userGroups = userConfig?.training?.allowed_course_groups ?? [];
1258
+ const userCourses = userConfig?.training?.allowed_courses ?? [];
1259
+ if (!orgGroups.length && !userGroups.length && !userCourses.length) return null;
1260
+ const foundationCourses = getCoursesByGroup("foundation");
1261
+ const orgCourseSlugs = orgGroups.flatMap(getCoursesByGroup);
1262
+ const userGroupCourseSlugs = userGroups.flatMap(getCoursesByGroup);
1263
+ return [.../* @__PURE__ */ new Set([...foundationCourses, ...orgCourseSlugs, ...userGroupCourseSlugs, ...userCourses])];
1264
+ }, [
1265
+ profile?.is_platform_admin,
1266
+ orgConfig?.training?.allowed_course_groups,
1267
+ userConfig?.training?.allowed_course_groups,
1268
+ userConfig?.training?.allowed_courses
1269
+ ]);
1270
+ const hasAccessToCourse = useCallback(
1271
+ (courseSlug) => {
1272
+ const resolved = getResolvedCourseAccess();
1273
+ if (resolved === null) return true;
1274
+ return resolved.includes(courseSlug);
1275
+ },
1276
+ [getResolvedCourseAccess]
1277
+ );
1278
+ const getEnabledGroups = useCallback(() => {
1279
+ const orgGroups = orgConfig?.training?.allowed_course_groups ?? [];
1280
+ const userGroups = userConfig?.training?.allowed_course_groups ?? [];
1281
+ return [.../* @__PURE__ */ new Set(["foundation", ...orgGroups, ...userGroups])];
1282
+ }, [orgConfig?.training?.allowed_course_groups, userConfig?.training?.allowed_course_groups]);
1283
+ return {
1284
+ orgConfig,
1285
+ membershipConfig,
1286
+ userConfig,
1287
+ hasFeature,
1288
+ checkFeature,
1289
+ hasTrainingAccess,
1290
+ getAllowedCourses,
1291
+ getResolvedCourseAccess,
1292
+ hasAccessToCourse,
1293
+ getEnabledGroups,
1294
+ isReady: organizationReady
1295
+ };
1296
+ };
1297
+ }
1298
+ function useSSEConnection({
1299
+ manager,
1300
+ connectionKey,
1301
+ url,
1302
+ enabled = true,
1303
+ headers,
1304
+ onmessage,
1305
+ onopen,
1306
+ onerror,
1307
+ onclose
1308
+ }) {
1309
+ const [connected, setConnected] = useState(false);
1310
+ const [error, setError] = useState(null);
1311
+ const getAccessToken = useStableAccessToken();
1312
+ const subscriberId = useId();
1313
+ const onmessageRef = useRef(onmessage);
1314
+ const onopenRef = useRef(onopen);
1315
+ const onerrorRef = useRef(onerror);
1316
+ const oncloseRef = useRef(onclose);
1317
+ const headersRef = useRef(headers);
1318
+ onmessageRef.current = onmessage;
1319
+ onopenRef.current = onopen;
1320
+ onerrorRef.current = onerror;
1321
+ oncloseRef.current = onclose;
1322
+ headersRef.current = headers;
1323
+ useEffect(() => {
1324
+ if (!enabled) return;
1325
+ const unsubscribe = manager.subscribe(connectionKey, subscriberId, {
1326
+ url,
1327
+ getToken: getAccessToken,
1328
+ headers: headersRef.current ?? {},
1329
+ onopen(response) {
1330
+ if (response.ok) {
1331
+ setConnected(true);
1332
+ setError(null);
1333
+ }
1334
+ const customError = onopenRef.current?.(response);
1335
+ if (customError) setError(customError);
1336
+ },
1337
+ onmessage(event) {
1338
+ if (!event.data || event.data.trim() === "") return;
1339
+ onmessageRef.current(event.data);
1340
+ },
1341
+ onerror(err) {
1342
+ const msg = err instanceof Error ? err.message : "Unknown error";
1343
+ setConnected(false);
1344
+ setError(msg);
1345
+ onerrorRef.current?.(err instanceof Error ? err : new Error(msg));
1346
+ },
1347
+ onclose() {
1348
+ setConnected(false);
1349
+ oncloseRef.current?.();
1350
+ }
1351
+ });
1352
+ return () => {
1353
+ unsubscribe();
1354
+ setConnected(false);
1355
+ setError(null);
1356
+ };
1357
+ }, [enabled, connectionKey, url, subscriberId, getAccessToken, manager]);
1358
+ return { connected, error };
1359
+ }
1066
1360
 
1067
- export { OperationsService, executionsKeys, observabilityKeys, scheduleKeys, useActivities, useActivityTrend, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorTrends, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutions, useGetExecutionHistory, useGetSchedule, useListSchedules, usePauseSchedule, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResumeSchedule, useRetryExecution, useTopFailingResources, useUnresolveError, useUpdateAnchor, useUpdateSchedule };
1361
+ export { OperationsService, createUseFeatureAccess, executionsKeys, observabilityKeys, scheduleKeys, sortData, useActivities, useActivityTrend, useBatchDelete, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useErrorTrends, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutions, useGetExecutionHistory, useGetSchedule, useListSchedules, usePaginationState, usePauseSchedule, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResumeSchedule, useRetryExecution, useSSEConnection, useSortedData, useSuccessNotification, useTableSelection, useTableSort, useTopFailingResources, useUnresolveError, useUpdateAnchor, useUpdateSchedule, useWarningNotification };
@@ -1,5 +1,5 @@
1
+ import { useNotificationAdapter } from './chunk-TIRMFDM4.js';
1
2
  import { useElevasisServices } from './chunk-KA7LO7U5.js';
2
- import { showApiErrorNotification } from './chunk-7AI5ZYJ4.js';
3
3
  import { useQueryClient, useMutation, useQuery } from '@tanstack/react-query';
4
4
  import { z } from 'zod';
5
5
 
@@ -26,6 +26,8 @@ z.object({
26
26
  startDate: z.string().datetime(),
27
27
  endDate: z.string().datetime()
28
28
  });
29
+
30
+ // ../core/src/operations/notifications/api-schemas.ts
29
31
  var NotificationCategorySchema = z.enum(["info", "queue", "alert", "error", "system"]);
30
32
  var GetNotificationsQuerySchema = z.object({
31
33
  limit: z.coerce.number().int().min(1).max(100).default(50),
@@ -47,6 +49,7 @@ z.object({
47
49
  function useMarkAsRead() {
48
50
  const queryClient = useQueryClient();
49
51
  const { apiRequest } = useElevasisServices();
52
+ const notify = useNotificationAdapter();
50
53
  return useMutation({
51
54
  mutationFn: async (notificationId) => {
52
55
  MarkAsReadParamsSchema.parse({ id: notificationId });
@@ -58,13 +61,14 @@ function useMarkAsRead() {
58
61
  queryClient.invalidateQueries({ queryKey: ["notifications"] });
59
62
  },
60
63
  onError: (error) => {
61
- showApiErrorNotification(error);
64
+ notify.apiError(error);
62
65
  }
63
66
  });
64
67
  }
65
68
  function useMarkAllAsRead() {
66
69
  const queryClient = useQueryClient();
67
70
  const { apiRequest } = useElevasisServices();
71
+ const notify = useNotificationAdapter();
68
72
  return useMutation({
69
73
  mutationFn: async () => {
70
74
  await apiRequest("/notifications/mark-all-read", {
@@ -75,7 +79,7 @@ function useMarkAllAsRead() {
75
79
  queryClient.invalidateQueries({ queryKey: ["notifications"] });
76
80
  },
77
81
  onError: (error) => {
78
- showApiErrorNotification(error);
82
+ notify.apiError(error);
79
83
  }
80
84
  });
81
85
  }
@@ -0,0 +1,15 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ // src/organization/context/OrganizationContext.tsx
4
+ var OrganizationContext = createContext(null);
5
+ function useOrganization() {
6
+ const ctx = useContext(OrganizationContext);
7
+ if (!ctx) {
8
+ throw new Error(
9
+ "useOrganization must be used within an OrganizationProvider. Wrap your app (or the relevant subtree) with <OrganizationProvider>."
10
+ );
11
+ }
12
+ return ctx;
13
+ }
14
+
15
+ export { OrganizationContext, useOrganization };
@@ -0,0 +1,13 @@
1
+ import { useAuthContext } from './chunk-7PLEQFHO.js';
2
+ import { useRef, useCallback } from 'react';
3
+
4
+ function useStableAccessToken() {
5
+ const { getAccessToken } = useAuthContext();
6
+ const getAccessTokenRef = useRef(getAccessToken);
7
+ getAccessTokenRef.current = getAccessToken;
8
+ return useCallback(() => {
9
+ return getAccessTokenRef.current();
10
+ }, []);
11
+ }
12
+
13
+ export { useStableAccessToken };
@@ -1,4 +1,4 @@
1
- import { useUserProfile } from './chunk-5UWFGBFM.js';
1
+ import { useUserProfile } from './chunk-L2CM2CUA.js';
2
2
  import { useAuthContext } from './chunk-7PLEQFHO.js';
3
3
  import { useState, useRef, useEffect, useCallback } from 'react';
4
4
  import { Button, Loader, Menu, Text, Badge } from '@mantine/core';
@@ -0,0 +1,47 @@
1
+ import { useAuthContext } from './chunk-7PLEQFHO.js';
2
+ import { createClient } from '@supabase/supabase-js';
3
+ import { useMemo } from 'react';
4
+
5
+ function getSupabaseConfig() {
6
+ const url = import.meta.env?.VITE_SUPABASE_URL;
7
+ const anonKey = import.meta.env?.VITE_SUPABASE_ANON_KEY;
8
+ if (!url || !anonKey) {
9
+ throw new Error("Missing Supabase environment variables (VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY)");
10
+ }
11
+ return { url, anonKey };
12
+ }
13
+ var _supabase = null;
14
+ function getSupabaseClient() {
15
+ if (!_supabase) {
16
+ const { url, anonKey } = getSupabaseConfig();
17
+ _supabase = createClient(url, anonKey);
18
+ }
19
+ return _supabase;
20
+ }
21
+ var useSupabase = () => {
22
+ const { getAccessToken } = useAuthContext();
23
+ const { url, anonKey } = getSupabaseConfig();
24
+ return useMemo(
25
+ () => createClient(url, anonKey, {
26
+ global: {
27
+ headers: {
28
+ // Additional headers if needed
29
+ }
30
+ },
31
+ accessToken: async () => {
32
+ try {
33
+ const token = await getAccessToken();
34
+ if (!token) {
35
+ return null;
36
+ }
37
+ return token;
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+ }),
43
+ [getAccessToken, url, anonKey]
44
+ );
45
+ };
46
+
47
+ export { getSupabaseClient, useSupabase };
@@ -1,99 +1,7 @@
1
+ import { getErrorInfo, formatErrorMessage, getErrorTitle } from './chunk-4VGWQ5AN.js';
1
2
  import { notifications } from '@mantine/notifications';
2
3
  import { IconUser, IconExternalLink, IconPlug, IconBolt, IconGitBranch, IconBrain } from '@tabler/icons-react';
3
4
 
4
- // src/utils/notify.tsx
5
-
6
- // src/utils/error-utils.ts
7
- var APIClientError = class extends Error {
8
- statusCode;
9
- code;
10
- requestId;
11
- fields;
12
- retryAfter;
13
- constructor(message, code, statusCode, requestId, fields, retryAfter) {
14
- super(message);
15
- this.name = "APIClientError";
16
- this.code = code;
17
- this.statusCode = statusCode;
18
- this.requestId = requestId;
19
- this.fields = fields;
20
- this.retryAfter = retryAfter;
21
- }
22
- };
23
- function isAPIClientError(error) {
24
- return error instanceof APIClientError;
25
- }
26
- function getErrorInfo(error) {
27
- if (isAPIClientError(error)) {
28
- return {
29
- message: error.message,
30
- code: error.code,
31
- requestId: error.requestId,
32
- statusCode: error.statusCode,
33
- fields: error.fields,
34
- retryAfter: error.retryAfter
35
- };
36
- }
37
- if (error instanceof Error) {
38
- return {
39
- message: error.message
40
- };
41
- }
42
- return {
43
- message: String(error)
44
- };
45
- }
46
- function getErrorTitle(code) {
47
- if (!code) return "Error";
48
- switch (code) {
49
- case "VALIDATION_ERROR":
50
- return "Validation Error";
51
- case "AUTHENTICATION_FAILED":
52
- return "Authentication Required";
53
- case "FORBIDDEN":
54
- return "Access Denied";
55
- case "NOT_FOUND":
56
- return "Not Found";
57
- case "CONFLICT":
58
- return "Conflict";
59
- case "RATE_LIMIT_EXCEEDED":
60
- return "Rate Limit Exceeded";
61
- case "INTERNAL_SERVER_ERROR":
62
- return "Server Error";
63
- case "SERVICE_UNAVAILABLE":
64
- return "Service Temporarily Unavailable";
65
- default:
66
- return "Error";
67
- }
68
- }
69
- function formatErrorMessage(message, requestId, fields, retryAfter) {
70
- let formatted = message;
71
- if (fields && Object.keys(fields).length > 0) {
72
- const fieldErrors = [];
73
- for (const [field, errors] of Object.entries(fields)) {
74
- const fieldName = field === "root" || field === "_root" ? "Request" : field;
75
- errors.forEach((error) => {
76
- fieldErrors.push(`\u2022 ${fieldName}: ${error}`);
77
- });
78
- }
79
- if (fieldErrors.length > 0) {
80
- formatted = fieldErrors.join("\n");
81
- }
82
- }
83
- if (retryAfter) {
84
- formatted += `
85
-
86
- Please wait ${retryAfter} seconds before retrying.`;
87
- }
88
- if (requestId) {
89
- formatted += `
90
-
91
- Request ID: ${requestId}`;
92
- }
93
- return formatted;
94
- }
95
-
96
- // src/utils/notify.tsx
97
5
  var showInfoNotification = (message) => {
98
6
  notifications.show({
99
7
  title: "Info",
@@ -199,4 +107,4 @@ function getResourceIcon(type) {
199
107
  return iconNameToComponent[iconName];
200
108
  }
201
109
 
202
- export { APIClientError, formatDate, formatErrorMessage, getErrorInfo, getErrorTitle, getResourceColor, getResourceIcon, isAPIClientError, showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, validateEmail };
110
+ export { formatDate, getResourceColor, getResourceIcon, showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, validateEmail };
@@ -1,7 +1,7 @@
1
- import { useSubmitAction, useDeleteTask } from './chunk-J3FALDQE.js';
1
+ import { useSubmitAction, useDeleteTask } from './chunk-NXHL23JW.js';
2
2
  import { FormFieldRenderer } from './chunk-PSLKGOBZ.js';
3
- import { ContextViewer, JsonViewer } from './chunk-OUHGHTE7.js';
4
- import { getErrorInfo, formatErrorMessage } from './chunk-7AI5ZYJ4.js';
3
+ import { ContextViewer, JsonViewer } from './chunk-O3PY6B6E.js';
4
+ import { getErrorInfo, formatErrorMessage } from './chunk-4VGWQ5AN.js';
5
5
  import { Modal, Stack, Title, Text, Textarea, Alert, Group, Button, Card, ThemeIcon, Badge, Loader, Menu, ActionIcon, Accordion } from '@mantine/core';
6
6
  import { IconMail, IconSend, IconFileText, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconAlertCircle, IconRobot, IconGitBranch, IconDotsVertical, IconTrash, IconPlayerPlay, IconExternalLink } from '@tabler/icons-react';
7
7
  import { useState } from 'react';
@@ -1,6 +1,6 @@
1
1
  import { useElevasisServices } from './chunk-KA7LO7U5.js';
2
2
  import { useAuthContext } from './chunk-7PLEQFHO.js';
3
- import { useState, useEffect } from 'react';
3
+ import { createContext, useState, useEffect, useContext, createElement } from 'react';
4
4
 
5
5
  // src/profile/services/UserProfileService.ts
6
6
  var UserProfileService = class {
@@ -65,8 +65,6 @@ var UserProfileService = class {
65
65
  }
66
66
  }
67
67
  };
68
-
69
- // src/profile/hooks/useUserProfile.ts
70
68
  var useUserProfile = (options) => {
71
69
  const { user, isLoading: authLoading } = useAuthContext();
72
70
  const { apiRequest } = useElevasisServices();
@@ -125,5 +123,19 @@ var useUserProfile = (options) => {
125
123
  refetch
126
124
  };
127
125
  };
126
+ var ProfileContext = createContext(null);
127
+ function useProfile() {
128
+ const ctx = useContext(ProfileContext);
129
+ if (!ctx) {
130
+ throw new Error(
131
+ "useProfile must be used within a ProfileProvider. Wrap your app (or the relevant subtree) with <ProfileProvider>."
132
+ );
133
+ }
134
+ return ctx;
135
+ }
136
+ function ProfileProvider({ children }) {
137
+ const value = useUserProfile();
138
+ return createElement(ProfileContext.Provider, { value }, children);
139
+ }
128
140
 
129
- export { UserProfileService, useUserProfile };
141
+ export { ProfileProvider, UserProfileService, useProfile, useUserProfile };
@@ -0,0 +1,75 @@
1
+ import { useProfile } from './chunk-L2CM2CUA.js';
2
+ import { useOrganization } from './chunk-DD3CCMCZ.js';
3
+ import { useAuthContext } from './chunk-7PLEQFHO.js';
4
+ import { createContext, useContext, useMemo, useCallback, createElement } from 'react';
5
+
6
+ var InitializationContext = createContext(null);
7
+ function useInitialization() {
8
+ const ctx = useContext(InitializationContext);
9
+ if (!ctx) {
10
+ throw new Error(
11
+ "useInitialization must be used within an InitializationProvider. Wrap your app (or the relevant subtree) with <InitializationProvider>."
12
+ );
13
+ }
14
+ return ctx;
15
+ }
16
+ function InitializationProvider({ children }) {
17
+ const { user, isLoading: authLoading } = useAuthContext();
18
+ const { profile, loading: profileLoading, error: profileError, refetch } = useProfile();
19
+ const {
20
+ isInitializing: orgInitializing,
21
+ isOrgRefreshing: orgLoading,
22
+ error: orgErrorMsg,
23
+ currentWorkOSOrganizationId,
24
+ memberships,
25
+ retry: orgRetry
26
+ } = useOrganization();
27
+ const isInitializing = authLoading || profileLoading || orgInitializing || orgLoading;
28
+ const userReady = !authLoading && !profileLoading && !!user && !!profile && !profileError;
29
+ const organizationReady = userReady && !orgInitializing && !orgLoading && !!currentWorkOSOrganizationId && !orgErrorMsg;
30
+ const allReady = organizationReady;
31
+ const error = useMemo(() => {
32
+ if (profileError) {
33
+ return {
34
+ layer: "profile",
35
+ message: "Failed to load user profile",
36
+ originalError: profileError
37
+ };
38
+ }
39
+ if (orgErrorMsg) {
40
+ return {
41
+ layer: "organization",
42
+ message: orgErrorMsg,
43
+ originalError: new Error(orgErrorMsg)
44
+ };
45
+ }
46
+ if (userReady && !orgInitializing && !orgLoading && !currentWorkOSOrganizationId && memberships.length > 0) {
47
+ return {
48
+ layer: "organization",
49
+ message: "No organization membership found. Please contact your administrator for an invitation."
50
+ };
51
+ }
52
+ return null;
53
+ }, [profileError, orgErrorMsg, userReady, orgInitializing, orgLoading, currentWorkOSOrganizationId, memberships]);
54
+ const retry = useCallback(async () => {
55
+ if (profileError && refetch) {
56
+ await refetch();
57
+ }
58
+ await orgRetry();
59
+ }, [profileError, refetch, orgRetry]);
60
+ const value = useMemo(
61
+ () => ({
62
+ userReady,
63
+ organizationReady,
64
+ allReady,
65
+ isInitializing,
66
+ error,
67
+ retry,
68
+ profile
69
+ }),
70
+ [userReady, organizationReady, allReady, isInitializing, error, retry, profile]
71
+ );
72
+ return createElement(InitializationContext.Provider, { value }, children);
73
+ }
74
+
75
+ export { InitializationContext, InitializationProvider, useInitialization };