@jmruthers/pace-core 0.5.139 → 0.5.141
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 +2 -2
- package/dist/{DataTable-JXFCA2BJ.js → DataTable-EGIN2NKK.js} +3 -3
- package/dist/{EventLogo-rFL_kRjk.d.ts → EventLogo-B3V3otev.d.ts} +307 -1
- package/dist/{chunk-BOOI7GK2.js → chunk-3R472UXR.js} +117 -1
- package/dist/chunk-3R472UXR.js.map +1 -0
- package/dist/{chunk-5JMOHWDI.js → chunk-ALUN6O3G.js} +492 -324
- package/dist/chunk-ALUN6O3G.js.map +1 -0
- package/dist/{chunk-6DXZ6V5Q.js → chunk-PZV3XZKJ.js} +2 -2
- package/dist/{chunk-TLT2ZR3L.js → chunk-WKTQM2IC.js} +2 -2
- package/dist/components.d.ts +3 -1
- package/dist/components.js +15 -3
- package/dist/components.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +18 -4
- package/dist/index.js.map +1 -1
- package/dist/rbac/index.d.ts +94 -1
- package/dist/rbac/index.js +4 -2
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +17 -5
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +2 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +40 -0
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +155 -0
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +9 -0
- package/docs/api/interfaces/TabsListProps.md +9 -0
- package/docs/api/interfaces/TabsProps.md +9 -0
- package/docs/api/interfaces/TabsTriggerProps.md +9 -0
- package/docs/api/interfaces/TextareaProps.md +53 -0
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +34 -0
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +289 -2
- package/docs/getting-started/examples/basic-auth-app.md +196 -0
- package/docs/getting-started/examples/full-featured-app.md +616 -0
- package/package.json +3 -1
- package/src/components/Calendar/Calendar.test.tsx +338 -0
- package/src/components/Calendar/Calendar.tsx +192 -0
- package/src/components/Calendar/index.ts +10 -0
- package/src/components/Tabs/Tabs.test.tsx +439 -0
- package/src/components/Tabs/Tabs.tsx +202 -0
- package/src/components/Tabs/index.ts +10 -0
- package/src/components/Textarea/Textarea.test.tsx +269 -0
- package/src/components/Textarea/Textarea.tsx +133 -0
- package/src/components/Textarea/index.ts +10 -0
- package/src/components/index.ts +11 -0
- package/src/index.ts +11 -0
- package/src/rbac/hooks/index.ts +2 -0
- package/src/rbac/hooks/useResourcePermissions.test.ts +633 -0
- package/src/rbac/hooks/useResourcePermissions.ts +235 -0
- package/src/utils/performance/bundleAnalysis.ts +17 -3
- package/dist/chunk-5JMOHWDI.js.map +0 -1
- package/dist/chunk-BOOI7GK2.js.map +0 -1
- /package/dist/{DataTable-JXFCA2BJ.js.map → DataTable-EGIN2NKK.js.map} +0 -0
- /package/dist/{chunk-6DXZ6V5Q.js.map → chunk-PZV3XZKJ.js.map} +0 -0
- /package/dist/{chunk-TLT2ZR3L.js.map → chunk-WKTQM2IC.js.map} +0 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file useResourcePermissions Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module RBAC/Hooks
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* Hook to check permissions for a specific resource type.
|
|
8
|
+
* This hook centralizes the common pattern of checking create/update/delete/read
|
|
9
|
+
* permissions, eliminating ~30 lines of boilerplate code per hook usage.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { useResourcePermissions } from '@jmruthers/pace-core/rbac';
|
|
14
|
+
*
|
|
15
|
+
* function ContactsHook() {
|
|
16
|
+
* const { canCreate, canUpdate, canDelete } = useResourcePermissions('contacts');
|
|
17
|
+
*
|
|
18
|
+
* const addContact = async (data: ContactData) => {
|
|
19
|
+
* if (!canCreate('contacts')) {
|
|
20
|
+
* throw new Error("Permission denied: You do not have permission to create contacts.");
|
|
21
|
+
* }
|
|
22
|
+
* // ... perform mutation
|
|
23
|
+
* };
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* // With read permissions enabled
|
|
30
|
+
* const { canRead } = useResourcePermissions('contacts', { enableRead: true });
|
|
31
|
+
*
|
|
32
|
+
* if (!canRead('contacts')) {
|
|
33
|
+
* return <PermissionDenied />;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @security
|
|
38
|
+
* - Requires organisation context (handled by useResolvedScope)
|
|
39
|
+
* - All permission checks are scoped to the current organisation/event/app context
|
|
40
|
+
* - Missing user context results in all permissions being denied
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import { useMemo } from 'react';
|
|
44
|
+
import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
|
|
45
|
+
import { useOrganisations } from '../../hooks/useOrganisations';
|
|
46
|
+
import { useEvents } from '../../hooks/useEvents';
|
|
47
|
+
import { useResolvedScope } from './useResolvedScope';
|
|
48
|
+
import { useCan } from './usePermissions';
|
|
49
|
+
import type { Scope } from '../types';
|
|
50
|
+
|
|
51
|
+
export interface UseResourcePermissionsOptions {
|
|
52
|
+
/** Whether to check read permissions (default: false) */
|
|
53
|
+
enableRead?: boolean;
|
|
54
|
+
/** Whether scope resolution is required (default: true) */
|
|
55
|
+
requireScope?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ResourcePermissions {
|
|
59
|
+
/** Check if user can create resources of this type */
|
|
60
|
+
canCreate: (resource: string) => boolean;
|
|
61
|
+
/** Check if user can update resources of this type */
|
|
62
|
+
canUpdate: (resource: string) => boolean;
|
|
63
|
+
/** Check if user can delete resources of this type */
|
|
64
|
+
canDelete: (resource: string) => boolean;
|
|
65
|
+
/** Check if user can read resources of this type */
|
|
66
|
+
canRead: (resource: string) => boolean;
|
|
67
|
+
/** The resolved scope object (for advanced use cases) */
|
|
68
|
+
scope: Scope;
|
|
69
|
+
/** Whether any permission check is currently loading */
|
|
70
|
+
isLoading: boolean;
|
|
71
|
+
/** Error from any permission check or scope resolution */
|
|
72
|
+
error: Error | null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Hook to check permissions for a specific resource
|
|
77
|
+
*
|
|
78
|
+
* This hook encapsulates the common pattern of checking create/update/delete/read
|
|
79
|
+
* permissions for a resource type. It handles scope resolution, user context,
|
|
80
|
+
* and provides a simple API for permission checking.
|
|
81
|
+
*
|
|
82
|
+
* @param resource - The resource name (e.g., 'contacts', 'risks', 'journal')
|
|
83
|
+
* @param options - Optional configuration
|
|
84
|
+
* @param options.enableRead - Whether to check read permissions (default: false)
|
|
85
|
+
* @param options.requireScope - Whether scope resolution is required (default: true)
|
|
86
|
+
* @returns Object with permission check functions and scope
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```tsx
|
|
90
|
+
* function useContacts() {
|
|
91
|
+
* const { canCreate, canUpdate, canDelete } = useResourcePermissions('contacts');
|
|
92
|
+
*
|
|
93
|
+
* const addContact = async (data: ContactData) => {
|
|
94
|
+
* if (!canCreate('contacts')) {
|
|
95
|
+
* throw new Error("Permission denied");
|
|
96
|
+
* }
|
|
97
|
+
* // ... perform mutation
|
|
98
|
+
* };
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export function useResourcePermissions(
|
|
103
|
+
resource: string,
|
|
104
|
+
options: UseResourcePermissionsOptions = {}
|
|
105
|
+
): ResourcePermissions {
|
|
106
|
+
const { enableRead = false, requireScope = true } = options;
|
|
107
|
+
|
|
108
|
+
// Get user and supabase client from UnifiedAuth
|
|
109
|
+
const { user, supabase } = useUnifiedAuth();
|
|
110
|
+
|
|
111
|
+
// Get selected organisation
|
|
112
|
+
const { selectedOrganisation } = useOrganisations();
|
|
113
|
+
|
|
114
|
+
// Get selected event (optional - wrap in try/catch)
|
|
115
|
+
let selectedEvent: { event_id: string } | null = null;
|
|
116
|
+
try {
|
|
117
|
+
const eventsContext = useEvents();
|
|
118
|
+
selectedEvent = eventsContext.selectedEvent;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
// Event provider not available - continue without event context
|
|
121
|
+
// This is expected in some apps that don't use events
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Resolve scope for permission checks
|
|
125
|
+
const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
|
|
126
|
+
supabase,
|
|
127
|
+
selectedOrganisationId: selectedOrganisation?.id || null,
|
|
128
|
+
selectedEventId: selectedEvent?.event_id || null
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Create fallback scope if resolvedScope is not available
|
|
132
|
+
const scope: Scope = resolvedScope || {
|
|
133
|
+
organisationId: selectedOrganisation?.id || '',
|
|
134
|
+
eventId: selectedEvent?.event_id || undefined,
|
|
135
|
+
appId: undefined
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Permission checks for create, update, delete
|
|
139
|
+
const { can: canCreateResult, isLoading: createLoading, error: createError } = useCan(
|
|
140
|
+
user?.id || '',
|
|
141
|
+
scope,
|
|
142
|
+
`create:${resource}` as const,
|
|
143
|
+
undefined, // pageId
|
|
144
|
+
true // useCache
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const { can: canUpdateResult, isLoading: updateLoading, error: updateError } = useCan(
|
|
148
|
+
user?.id || '',
|
|
149
|
+
scope,
|
|
150
|
+
`update:${resource}` as const,
|
|
151
|
+
undefined, // pageId
|
|
152
|
+
true // useCache
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const { can: canDeleteResult, isLoading: deleteLoading, error: deleteError } = useCan(
|
|
156
|
+
user?.id || '',
|
|
157
|
+
scope,
|
|
158
|
+
`delete:${resource}` as const,
|
|
159
|
+
undefined, // pageId
|
|
160
|
+
true // useCache
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Optional read permission check
|
|
164
|
+
const { can: canReadResult, isLoading: readLoading, error: readError } = useCan(
|
|
165
|
+
user?.id || '',
|
|
166
|
+
scope,
|
|
167
|
+
`read:${resource}` as const,
|
|
168
|
+
undefined, // pageId
|
|
169
|
+
true // useCache
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// Aggregate loading states - any permission check or scope resolution loading
|
|
173
|
+
const isLoading = useMemo(() => {
|
|
174
|
+
return scopeLoading || createLoading || updateLoading || deleteLoading || (enableRead && readLoading);
|
|
175
|
+
}, [scopeLoading, createLoading, updateLoading, deleteLoading, readLoading, enableRead]);
|
|
176
|
+
|
|
177
|
+
// Aggregate errors - prefer scope error, then any permission error
|
|
178
|
+
const error = useMemo(() => {
|
|
179
|
+
if (scopeError) return scopeError;
|
|
180
|
+
if (createError) return createError;
|
|
181
|
+
if (updateError) return updateError;
|
|
182
|
+
if (deleteError) return deleteError;
|
|
183
|
+
if (enableRead && readError) return readError;
|
|
184
|
+
return null;
|
|
185
|
+
}, [scopeError, createError, updateError, deleteError, readError, enableRead]);
|
|
186
|
+
|
|
187
|
+
// Return wrapper functions that take resource name and return permission result
|
|
188
|
+
// Note: The resource parameter in the function is for consistency with the API,
|
|
189
|
+
// but we're checking permissions for the resource passed to the hook
|
|
190
|
+
return useMemo(() => ({
|
|
191
|
+
canCreate: (res: string) => {
|
|
192
|
+
// For now, we only check the resource passed to the hook
|
|
193
|
+
// Future enhancement could support checking different resources
|
|
194
|
+
if (res !== resource) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
return canCreateResult;
|
|
198
|
+
},
|
|
199
|
+
canUpdate: (res: string) => {
|
|
200
|
+
if (res !== resource) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
return canUpdateResult;
|
|
204
|
+
},
|
|
205
|
+
canDelete: (res: string) => {
|
|
206
|
+
if (res !== resource) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return canDeleteResult;
|
|
210
|
+
},
|
|
211
|
+
canRead: (res: string) => {
|
|
212
|
+
if (!enableRead) {
|
|
213
|
+
return true; // If read checking is disabled, allow read
|
|
214
|
+
}
|
|
215
|
+
if (res !== resource) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
return canReadResult;
|
|
219
|
+
},
|
|
220
|
+
scope,
|
|
221
|
+
isLoading,
|
|
222
|
+
error
|
|
223
|
+
}), [
|
|
224
|
+
resource,
|
|
225
|
+
canCreateResult,
|
|
226
|
+
canUpdateResult,
|
|
227
|
+
canDeleteResult,
|
|
228
|
+
canReadResult,
|
|
229
|
+
enableRead,
|
|
230
|
+
scope,
|
|
231
|
+
isLoading,
|
|
232
|
+
error
|
|
233
|
+
]);
|
|
234
|
+
}
|
|
235
|
+
|
|
@@ -14,7 +14,13 @@ interface ChunkInfo {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
class BundleAnalyzer {
|
|
17
|
-
private enabled
|
|
17
|
+
private get enabled(): boolean {
|
|
18
|
+
try {
|
|
19
|
+
return import.meta.env?.MODE === 'development';
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
18
24
|
|
|
19
25
|
analyzeBundle(): BundleStats | null {
|
|
20
26
|
if (!this.enabled) return null;
|
|
@@ -104,7 +110,11 @@ export const bundleAnalyzer = new BundleAnalyzer();
|
|
|
104
110
|
|
|
105
111
|
// Helper to check if imports are optimized
|
|
106
112
|
export function validateImportPattern(moduleId: string, importedItems: string[]): void {
|
|
107
|
-
|
|
113
|
+
try {
|
|
114
|
+
if (import.meta.env?.MODE !== 'development') return;
|
|
115
|
+
} catch {
|
|
116
|
+
return; // Silently skip in test environments
|
|
117
|
+
}
|
|
108
118
|
|
|
109
119
|
const largeModules = ['lodash', 'moment', 'rxjs'];
|
|
110
120
|
const isLargeModule = largeModules.some(mod => moduleId.includes(mod));
|
|
@@ -121,7 +131,11 @@ export function validateImportPattern(moduleId: string, importedItems: string[])
|
|
|
121
131
|
|
|
122
132
|
// Monitor dynamic imports
|
|
123
133
|
export function trackDynamicImport(moduleName: string): void {
|
|
124
|
-
|
|
134
|
+
try {
|
|
135
|
+
if (import.meta.env?.MODE !== 'development') return;
|
|
136
|
+
} catch {
|
|
137
|
+
return; // Silently skip in test environments
|
|
138
|
+
}
|
|
125
139
|
|
|
126
140
|
// TODO: Replace with proper logging service integration
|
|
127
141
|
// For now, we'll log to console for testing purposes
|