@jmruthers/pace-core 0.6.6 → 0.6.8
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +240 -0
- package/audit-tool/audits/03-architecture.cjs +224 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +554 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +295 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +380 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-6RMSCQJ6.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
- package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
- package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
- package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
- package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
- package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
- package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
- package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
- package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
- package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
- package/dist/components.d.ts +5 -4
- package/dist/components.js +29 -34
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +8 -8
- package/dist/index.d.ts +7 -7
- package/dist/index.js +21 -20
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +1 -1
- package/dist/rbac/index.js +8 -8
- package/dist/theming/runtime.d.ts +61 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +106 -41
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/dependencies.md +23 -0
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/app-layout.md +1 -1
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +127 -34
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +50 -20
- package/package.json +50 -19
- package/scripts/eslint-audit.cjs +123 -0
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +349 -0
- package/scripts/validate-dependencies.cjs +248 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/AddressField/AddressField.tsx +26 -1
- package/src/components/Alert/Alert.test.tsx +86 -22
- package/src/components/Alert/Alert.tsx +19 -11
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/Checkbox/Checkbox.test.tsx +2 -1
- package/src/components/ContextSelector/ContextSelector.tsx +108 -126
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/DataTable.tsx +1 -19
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +11 -10
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +45 -16
- package/src/components/FileUpload/FileUpload.tsx +141 -130
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +13 -9
- package/src/hooks/useAddressAutocomplete.test.ts +18 -18
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +2 -1
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/hooks/useFileUrl.ts +52 -8
- package/src/hooks/useOrganisationSecurity.test.ts +2 -1
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
- package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
- package/src/rbac/api.test.ts +104 -0
- package/src/rbac/engine.ts +1 -1
- package/src/rbac/hooks/useCan.test.ts +2 -2
- package/src/rbac/secureClient.ts +1 -1
- package/src/rbac/types/functions.ts +1 -1
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +118 -3
- package/src/theming/parseEventColours.ts +77 -11
- package/src/types/supabase.ts +2 -3
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
- package/src/utils/formatting/formatDate.test.ts +3 -2
- package/src/utils/formatting/formatDateTime.test.ts +2 -2
- package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
- package/src/utils/storage/README.md +1 -1
- package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
- package/src/utils/storage/helpers.test.ts +69 -3
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
package/src/rbac/api.test.ts
CHANGED
|
@@ -191,6 +191,14 @@ describe('RBAC API', () => {
|
|
|
191
191
|
|
|
192
192
|
it('handles engine creation errors gracefully', () => {
|
|
193
193
|
const error = new Error('Engine creation error');
|
|
194
|
+
// Ensure createRBACConfig doesn't throw so we can test engine creation error
|
|
195
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
196
|
+
mockGetRBACLogger.mockReturnValue({
|
|
197
|
+
info: vi.fn(),
|
|
198
|
+
warn: vi.fn(),
|
|
199
|
+
error: vi.fn(),
|
|
200
|
+
debug: vi.fn()
|
|
201
|
+
});
|
|
194
202
|
mockCreateRBACEngine.mockImplementation(() => {
|
|
195
203
|
throw error;
|
|
196
204
|
});
|
|
@@ -202,6 +210,16 @@ describe('RBAC API', () => {
|
|
|
202
210
|
|
|
203
211
|
it('handles audit manager creation errors gracefully', () => {
|
|
204
212
|
const error = new Error('Audit manager creation error');
|
|
213
|
+
// Ensure createRBACConfig doesn't throw so we can test audit manager creation error
|
|
214
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
215
|
+
mockGetRBACLogger.mockReturnValue({
|
|
216
|
+
info: vi.fn(),
|
|
217
|
+
warn: vi.fn(),
|
|
218
|
+
error: vi.fn(),
|
|
219
|
+
debug: vi.fn()
|
|
220
|
+
});
|
|
221
|
+
const mockEngine = { id: 'test-engine' };
|
|
222
|
+
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
205
223
|
mockCreateAuditManager.mockImplementation(() => {
|
|
206
224
|
throw error;
|
|
207
225
|
});
|
|
@@ -309,6 +327,21 @@ describe('RBAC API', () => {
|
|
|
309
327
|
|
|
310
328
|
describe('Error Handling', () => {
|
|
311
329
|
it('handles missing supabase client', () => {
|
|
330
|
+
const mockEngine = { id: 'test-engine' };
|
|
331
|
+
const mockAuditManager = { id: 'test-audit' };
|
|
332
|
+
const mockLogger = {
|
|
333
|
+
info: vi.fn(),
|
|
334
|
+
warn: vi.fn(),
|
|
335
|
+
error: vi.fn(),
|
|
336
|
+
debug: vi.fn()
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// Ensure mocks don't throw
|
|
340
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
341
|
+
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
342
|
+
mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
|
|
343
|
+
mockGetRBACLogger.mockReturnValue(mockLogger);
|
|
344
|
+
|
|
312
345
|
// The function doesn't throw, it just creates config with null
|
|
313
346
|
expect(() => {
|
|
314
347
|
setupRBAC(null as any);
|
|
@@ -317,6 +350,20 @@ describe('RBAC API', () => {
|
|
|
317
350
|
|
|
318
351
|
it('handles invalid supabase client', () => {
|
|
319
352
|
const invalidSupabase = { invalid: 'client' };
|
|
353
|
+
const mockEngine = { id: 'test-engine' };
|
|
354
|
+
const mockAuditManager = { id: 'test-audit' };
|
|
355
|
+
const mockLogger = {
|
|
356
|
+
info: vi.fn(),
|
|
357
|
+
warn: vi.fn(),
|
|
358
|
+
error: vi.fn(),
|
|
359
|
+
debug: vi.fn()
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// Ensure mocks don't throw
|
|
363
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
364
|
+
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
365
|
+
mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
|
|
366
|
+
mockGetRBACLogger.mockReturnValue(mockLogger);
|
|
320
367
|
|
|
321
368
|
// The function doesn't throw, it just creates config with invalid client
|
|
322
369
|
expect(() => {
|
|
@@ -354,6 +401,21 @@ describe('RBAC API', () => {
|
|
|
354
401
|
|
|
355
402
|
describe('Configuration Validation', () => {
|
|
356
403
|
it('validates required supabase client', () => {
|
|
404
|
+
const mockEngine = { id: 'test-engine' };
|
|
405
|
+
const mockAuditManager = { id: 'test-audit' };
|
|
406
|
+
const mockLogger = {
|
|
407
|
+
info: vi.fn(),
|
|
408
|
+
warn: vi.fn(),
|
|
409
|
+
error: vi.fn(),
|
|
410
|
+
debug: vi.fn()
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
// Ensure mocks don't throw
|
|
414
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
415
|
+
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
416
|
+
mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
|
|
417
|
+
mockGetRBACLogger.mockReturnValue(mockLogger);
|
|
418
|
+
|
|
357
419
|
// The function doesn't throw, it just creates config with undefined
|
|
358
420
|
expect(() => {
|
|
359
421
|
setupRBAC(undefined as any);
|
|
@@ -365,6 +427,20 @@ describe('RBAC API', () => {
|
|
|
365
427
|
from: 'not-a-function',
|
|
366
428
|
auth: 'not-an-object'
|
|
367
429
|
};
|
|
430
|
+
const mockEngine = { id: 'test-engine' };
|
|
431
|
+
const mockAuditManager = { id: 'test-audit' };
|
|
432
|
+
const mockLogger = {
|
|
433
|
+
info: vi.fn(),
|
|
434
|
+
warn: vi.fn(),
|
|
435
|
+
error: vi.fn(),
|
|
436
|
+
debug: vi.fn()
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// Ensure mocks don't throw
|
|
440
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
441
|
+
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
442
|
+
mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
|
|
443
|
+
mockGetRBACLogger.mockReturnValue(mockLogger);
|
|
368
444
|
|
|
369
445
|
// The function doesn't throw, it just creates config with invalid client
|
|
370
446
|
expect(() => {
|
|
@@ -415,6 +491,32 @@ describe('RBAC API', () => {
|
|
|
415
491
|
});
|
|
416
492
|
});
|
|
417
493
|
|
|
494
|
+
describe('Type Safety', () => {
|
|
495
|
+
it('accepts valid Supabase client types', () => {
|
|
496
|
+
const validSupabase = {
|
|
497
|
+
from: vi.fn(),
|
|
498
|
+
auth: { getUser: vi.fn() },
|
|
499
|
+
rpc: vi.fn()
|
|
500
|
+
};
|
|
501
|
+
const mockEngine = { id: 'test-engine' };
|
|
502
|
+
const mockAuditManager = { id: 'test-audit' };
|
|
503
|
+
const mockLogger = {
|
|
504
|
+
info: vi.fn(),
|
|
505
|
+
warn: vi.fn(),
|
|
506
|
+
error: vi.fn(),
|
|
507
|
+
debug: vi.fn()
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
511
|
+
mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
|
|
512
|
+
mockGetRBACLogger.mockReturnValue(mockLogger);
|
|
513
|
+
|
|
514
|
+
expect(() => {
|
|
515
|
+
setupRBAC(validSupabase as any);
|
|
516
|
+
}).not.toThrow();
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
|
|
418
520
|
describe('Cache Integration', () => {
|
|
419
521
|
it('initializes cache correctly', () => {
|
|
420
522
|
const mockEngine = { id: 'test-engine' };
|
|
@@ -456,6 +558,8 @@ describe('RBAC API', () => {
|
|
|
456
558
|
debug: vi.fn()
|
|
457
559
|
};
|
|
458
560
|
|
|
561
|
+
// Ensure mocks don't throw
|
|
562
|
+
mockCreateRBACConfig.mockImplementation((config) => config);
|
|
459
563
|
mockCreateRBACEngine.mockReturnValue(mockEngine as any);
|
|
460
564
|
mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
|
|
461
565
|
mockGetRBACLogger.mockReturnValue(mockLogger);
|
package/src/rbac/engine.ts
CHANGED
|
@@ -440,7 +440,7 @@ export class RBACEngine {
|
|
|
440
440
|
async resolveAppContext(input: { userId: UUID; appName: string }): Promise<RBACAppContext | null> {
|
|
441
441
|
try {
|
|
442
442
|
const { userId, appName } = input;
|
|
443
|
-
const { data, error } = await (this.supabase as any).rpc('
|
|
443
|
+
const { data, error } = await (this.supabase as any).rpc('data_app_resolve', {
|
|
444
444
|
p_user_id: userId,
|
|
445
445
|
p_app_name: appName,
|
|
446
446
|
});
|
|
@@ -647,7 +647,7 @@ describe('useCan Hook', () => {
|
|
|
647
647
|
}, { timeout: 20000 });
|
|
648
648
|
});
|
|
649
649
|
|
|
650
|
-
it('times out after 3 seconds when organisationId is missing', async () => {
|
|
650
|
+
it('times out after 3 seconds when organisationId is missing', { timeout: 10000 }, async () => {
|
|
651
651
|
vi.useFakeTimers({ shouldAdvanceTime: true });
|
|
652
652
|
|
|
653
653
|
const emptyScope = {} as any;
|
|
@@ -672,7 +672,7 @@ describe('useCan Hook', () => {
|
|
|
672
672
|
expect(result.current.error).not.toBeNull();
|
|
673
673
|
expect(result.current.error?.message).toBe('Organisation context is required for permission checks');
|
|
674
674
|
}, { timeout: 2000 });
|
|
675
|
-
}
|
|
675
|
+
});
|
|
676
676
|
|
|
677
677
|
it('handles null userId', async () => {
|
|
678
678
|
const { result } = renderHook(() =>
|
package/src/rbac/secureClient.ts
CHANGED
|
@@ -536,7 +536,7 @@ export class SecureSupabaseClient {
|
|
|
536
536
|
// 2. Add it here with the parameters it accepts
|
|
537
537
|
const rpcContextWhitelist: Record<string, Set<string>> = {
|
|
538
538
|
// RPCs that accept all three context parameters
|
|
539
|
-
'
|
|
539
|
+
'data_rbac_roles_list': new Set(['p_organisation_id', 'p_event_id', 'p_app_id']),
|
|
540
540
|
|
|
541
541
|
// RPCs that accept only p_organisation_id (not p_app_id or p_event_id)
|
|
542
542
|
'data_file_reference_by_category_list': new Set(['p_organisation_id']),
|
|
@@ -185,7 +185,7 @@ export enum RPCFunction {
|
|
|
185
185
|
// Role Management Functions
|
|
186
186
|
RBAC_ROLE_GRANT = 'rbac_role_grant',
|
|
187
187
|
RBAC_ROLE_REVOKE = 'rbac_role_revoke',
|
|
188
|
-
RBAC_ROLES_LIST = '
|
|
188
|
+
RBAC_ROLES_LIST = 'data_rbac_roles_list',
|
|
189
189
|
RBAC_ROLE_VALIDATE = 'rbac_role_validate',
|
|
190
190
|
|
|
191
191
|
// Session & Audit Functions
|
package/src/styles/core.css
CHANGED
|
@@ -206,6 +206,13 @@
|
|
|
206
206
|
dialog::backdrop {
|
|
207
207
|
background-color: oklch(from var(--color-main-700) l c h / 0.5);
|
|
208
208
|
}
|
|
209
|
+
|
|
210
|
+
progress::indeterminate {
|
|
211
|
+
|
|
212
|
+
background: var(--color-acc-600);
|
|
213
|
+
/*
|
|
214
|
+
background: linear-gradient(to right, var(--color-acc-700) 10%, var(--color-sec-200) 30%, var(--color-main-500) 70%, var(--color-acc-200) 90%); */
|
|
215
|
+
}
|
|
209
216
|
|
|
210
217
|
.appGradient {
|
|
211
218
|
background: linear-gradient(145deg, var(--color-main-100) 10%, var(--color-main-200) 30%, var(--color-main-200) 70%, var(--color-main-300) 90%);
|
|
@@ -88,7 +88,7 @@ describe('parseAndNormalizeEventColours', () => {
|
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
describe('Standard format only', () => {
|
|
91
|
-
it('
|
|
91
|
+
it('supports ev-main, ev-sec, ev-acc keys and normalizes them', () => {
|
|
92
92
|
const input = {
|
|
93
93
|
'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
|
|
94
94
|
'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
|
|
@@ -96,8 +96,11 @@ describe('parseAndNormalizeEventColours', () => {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
const result = parseAndNormalizeEventColours(input);
|
|
99
|
-
//
|
|
100
|
-
expect(result).toBeNull();
|
|
99
|
+
// ev-main, ev-sec, ev-acc keys are supported and normalized to main, sec, acc
|
|
100
|
+
expect(result).not.toBeNull();
|
|
101
|
+
expect(result?.main[500]).toEqual({ L: 0.5, C: 0.2, H: 0 });
|
|
102
|
+
expect(result?.sec[500]).toEqual({ L: 0.5, C: 0.2, H: 120 });
|
|
103
|
+
expect(result?.acc[500]).toEqual({ L: 0.5, C: 0.2, H: 240 });
|
|
101
104
|
});
|
|
102
105
|
|
|
103
106
|
it('uses standard keys when provided', () => {
|
|
@@ -192,6 +195,118 @@ describe('parseAndNormalizeEventColours', () => {
|
|
|
192
195
|
});
|
|
193
196
|
});
|
|
194
197
|
|
|
198
|
+
describe('ev- prefix handling for shade names', () => {
|
|
199
|
+
it('strips ev- prefix from shade names', () => {
|
|
200
|
+
const input = {
|
|
201
|
+
main: {
|
|
202
|
+
'ev-main-500': { L: 0.5, C: 0.2, H: 0 },
|
|
203
|
+
'ev-main-100': { L: 0.9, C: 0.1, H: 0 }
|
|
204
|
+
},
|
|
205
|
+
acc: {
|
|
206
|
+
'ev-acc-500': { L: 0.5, C: 0.2, H: 240 }
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const result = parseAndNormalizeEventColours(input);
|
|
211
|
+
expect(result).not.toBeNull();
|
|
212
|
+
|
|
213
|
+
// ev- prefix should be stripped from shade names
|
|
214
|
+
expect(result?.main['main-500']).toEqual({ L: 0.5, C: 0.2, H: 0 });
|
|
215
|
+
expect(result?.main['main-100']).toEqual({ L: 0.9, C: 0.1, H: 0 });
|
|
216
|
+
expect(result?.acc['acc-500']).toEqual({ L: 0.5, C: 0.2, H: 240 });
|
|
217
|
+
|
|
218
|
+
// Original keys with ev- prefix should not exist
|
|
219
|
+
expect(result?.main['ev-main-500']).toBeUndefined();
|
|
220
|
+
expect(result?.main['ev-main-100']).toBeUndefined();
|
|
221
|
+
expect(result?.acc['ev-acc-500']).toBeUndefined();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('handles mixed ev- prefixed and non-prefixed shade names', () => {
|
|
225
|
+
const input = {
|
|
226
|
+
main: {
|
|
227
|
+
'ev-main-500': { L: 0.5, C: 0.2, H: 0 },
|
|
228
|
+
100: { L: 0.9, C: 0.1, H: 0 },
|
|
229
|
+
raw: { L: 0.55, C: 0.25, H: 5 }
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const result = parseAndNormalizeEventColours(input);
|
|
234
|
+
expect(result).not.toBeNull();
|
|
235
|
+
|
|
236
|
+
// ev- prefixed shade should be normalized
|
|
237
|
+
expect(result?.main['main-500']).toEqual({ L: 0.5, C: 0.2, H: 0 });
|
|
238
|
+
|
|
239
|
+
// Non-prefixed shades should remain unchanged
|
|
240
|
+
expect(result?.main[100]).toEqual({ L: 0.9, C: 0.1, H: 0 });
|
|
241
|
+
expect(result?.main.raw).toEqual({ L: 0.55, C: 0.25, H: 5 });
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('handles ev- prefixed shade names in sec palette', () => {
|
|
245
|
+
const input = {
|
|
246
|
+
sec: {
|
|
247
|
+
'ev-sec-500': { L: 0.5, C: 0.2, H: 120 },
|
|
248
|
+
'ev-sec-200': { L: 0.8, C: 0.15, H: 120 }
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const result = parseAndNormalizeEventColours(input);
|
|
253
|
+
expect(result).not.toBeNull();
|
|
254
|
+
|
|
255
|
+
expect(result?.sec['sec-500']).toEqual({ L: 0.5, C: 0.2, H: 120 });
|
|
256
|
+
expect(result?.sec['sec-200']).toEqual({ L: 0.8, C: 0.15, H: 120 });
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('preserves shade names that do not start with ev-', () => {
|
|
260
|
+
const input = {
|
|
261
|
+
main: {
|
|
262
|
+
500: { L: 0.5, C: 0.2, H: 0 },
|
|
263
|
+
'main-500': { L: 0.6, C: 0.3, H: 0 },
|
|
264
|
+
raw: { L: 0.55, C: 0.25, H: 5 }
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const result = parseAndNormalizeEventColours(input);
|
|
269
|
+
expect(result).not.toBeNull();
|
|
270
|
+
|
|
271
|
+
// All shades should be preserved as-is (no ev- prefix to strip)
|
|
272
|
+
expect(result?.main[500]).toEqual({ L: 0.5, C: 0.2, H: 0 });
|
|
273
|
+
expect(result?.main['main-500']).toEqual({ L: 0.6, C: 0.3, H: 0 });
|
|
274
|
+
expect(result?.main.raw).toEqual({ L: 0.55, C: 0.25, H: 5 });
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('normalizes both palette keys and shade names with ev- prefix together', () => {
|
|
278
|
+
const input = {
|
|
279
|
+
'ev-main': {
|
|
280
|
+
'ev-main-raw': { L: 0.55, C: 0.25, H: 5 },
|
|
281
|
+
'ev-main-200': { L: 0.8, C: 0.15, H: 0 }
|
|
282
|
+
},
|
|
283
|
+
'ev-sec': {
|
|
284
|
+
'ev-sec-200': { L: 0.8, C: 0.15, H: 120 },
|
|
285
|
+
'ev-sec-500': { L: 0.5, C: 0.2, H: 120 }
|
|
286
|
+
},
|
|
287
|
+
'ev-acc': {
|
|
288
|
+
'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const result = parseAndNormalizeEventColours(input);
|
|
293
|
+
expect(result).not.toBeNull();
|
|
294
|
+
|
|
295
|
+
// Palette keys should be normalized: ev-main -> main, ev-sec -> sec, ev-acc -> acc
|
|
296
|
+
// Shade names should be normalized: ev-main-raw -> main-raw, ev-sec-200 -> sec-200, etc.
|
|
297
|
+
expect(result?.main['main-raw']).toEqual({ L: 0.55, C: 0.25, H: 5 });
|
|
298
|
+
expect(result?.main['main-200']).toEqual({ L: 0.8, C: 0.15, H: 0 });
|
|
299
|
+
expect(result?.sec['sec-200']).toEqual({ L: 0.8, C: 0.15, H: 120 });
|
|
300
|
+
expect(result?.sec['sec-500']).toEqual({ L: 0.5, C: 0.2, H: 120 });
|
|
301
|
+
expect(result?.acc['acc-800']).toEqual({ L: 0.3, C: 0.2, H: 240 });
|
|
302
|
+
|
|
303
|
+
// Original keys should not exist
|
|
304
|
+
expect(result?.main['ev-main-raw']).toBeUndefined();
|
|
305
|
+
expect(result?.sec['ev-sec-200']).toBeUndefined();
|
|
306
|
+
expect(result?.acc['ev-acc-800']).toBeUndefined();
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
|
|
195
310
|
describe('Error handling', () => {
|
|
196
311
|
it('handles malformed color objects gracefully', () => {
|
|
197
312
|
const input = {
|
|
@@ -8,21 +8,28 @@
|
|
|
8
8
|
* Handles multiple input formats and ensures consistent palette structure.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { createLogger } from '../utils/core/logger';
|
|
12
|
-
|
|
13
|
-
const log = createLogger('ParseEventColours');
|
|
14
11
|
|
|
15
12
|
/**
|
|
16
13
|
* Parse and normalize event_colours to PaletteData
|
|
17
14
|
*
|
|
18
15
|
* Supports input formats:
|
|
19
|
-
* - Object with 'main', 'sec', 'acc' keys
|
|
16
|
+
* - Object with 'main', 'sec', 'acc' keys (standard format)
|
|
17
|
+
* - Object with 'ev-main', 'ev-sec', 'ev-acc' keys (database format with prefix)
|
|
18
|
+
* - Shade names with 'ev-' prefix (e.g., 'ev-acc-500' -> 'acc-500', 'ev-main-raw' -> 'main-raw')
|
|
20
19
|
* - JSON string that will be parsed
|
|
21
20
|
*
|
|
22
21
|
* Only includes explicitly defined color values. Does not fill
|
|
23
22
|
* missing shades - only shades that are present in the input will
|
|
24
23
|
* be included in the output.
|
|
25
24
|
*
|
|
25
|
+
* The parser automatically strips 'ev-' prefixes from BOTH palette keys and shade names
|
|
26
|
+
* for future-proofing, allowing distinction between event colors and organization colors
|
|
27
|
+
* (org colors not yet implemented).
|
|
28
|
+
*
|
|
29
|
+
* Normalization rules:
|
|
30
|
+
* - Palette keys: 'ev-main' -> 'main', 'ev-sec' -> 'sec', 'ev-acc' -> 'acc'
|
|
31
|
+
* - Shade names: 'ev-main-raw' -> 'main-raw', 'ev-sec-200' -> 'sec-200', 'ev-acc-800' -> 'acc-800'
|
|
32
|
+
*
|
|
26
33
|
* @param input - Event colours from database (JSONB field)
|
|
27
34
|
* @returns Normalized palette data with main, sec, acc palettes, or null if invalid
|
|
28
35
|
*
|
|
@@ -38,6 +45,56 @@ const log = createLogger('ParseEventColours');
|
|
|
38
45
|
* // Returns: { main: { 500: {...}, raw: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
|
|
39
46
|
* ```
|
|
40
47
|
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* // Database format with ev- prefix on palette keys
|
|
51
|
+
* const colours = {
|
|
52
|
+
* 'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
|
|
53
|
+
* 'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
|
|
54
|
+
* 'ev-acc': { 500: { L: 0.5, C: 0.2, H: 240 } }
|
|
55
|
+
* };
|
|
56
|
+
* const palette = parseAndNormalizeEventColours(colours);
|
|
57
|
+
* // Returns: { main: { 500: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* // Future-proofing: ev- prefix on shade names
|
|
63
|
+
* const colours = {
|
|
64
|
+
* main: {
|
|
65
|
+
* 'ev-main-500': { L: 0.5, C: 0.2, H: 0 },
|
|
66
|
+
* 'ev-main-raw': { L: 0.55, C: 0.25, H: 5 }
|
|
67
|
+
* },
|
|
68
|
+
* sec: {
|
|
69
|
+
* 'ev-sec-200': { L: 0.8, C: 0.15, H: 120 }
|
|
70
|
+
* },
|
|
71
|
+
* acc: {
|
|
72
|
+
* 'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
|
|
73
|
+
* }
|
|
74
|
+
* };
|
|
75
|
+
* const palette = parseAndNormalizeEventColours(colours);
|
|
76
|
+
* // Returns: { main: { 'main-500': {...}, 'main-raw': {...} }, sec: { 'sec-200': {...} }, acc: { 'acc-800': {...} } }
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* // Both palette keys and shade names with ev- prefix
|
|
82
|
+
* const colours = {
|
|
83
|
+
* 'ev-main': {
|
|
84
|
+
* 'ev-main-raw': { L: 0.55, C: 0.25, H: 5 },
|
|
85
|
+
* 'ev-main-200': { L: 0.8, C: 0.15, H: 0 }
|
|
86
|
+
* },
|
|
87
|
+
* 'ev-sec': {
|
|
88
|
+
* 'ev-sec-500': { L: 0.5, C: 0.2, H: 120 }
|
|
89
|
+
* },
|
|
90
|
+
* 'ev-acc': {
|
|
91
|
+
* 'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
|
|
92
|
+
* }
|
|
93
|
+
* };
|
|
94
|
+
* const palette = parseAndNormalizeEventColours(colours);
|
|
95
|
+
* // Returns: { main: { 'main-raw': {...}, 'main-200': {...} }, sec: { 'sec-500': {...} }, acc: { 'acc-800': {...} } }
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
41
98
|
*/
|
|
42
99
|
export function parseAndNormalizeEventColours(input: unknown): { main: any; sec: any; acc: any } | null {
|
|
43
100
|
try {
|
|
@@ -55,16 +112,21 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
|
|
|
55
112
|
return null;
|
|
56
113
|
}
|
|
57
114
|
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
115
|
+
// Support both standard keys (main/sec/acc) and prefixed keys (ev-main/ev-sec/ev-acc)
|
|
116
|
+
// Database may store with ev-* prefix, but we normalize to standard keys
|
|
117
|
+
const main = obj?.main || obj?.['ev-main'] || null;
|
|
118
|
+
const sec = obj?.sec || obj?.['ev-sec'] || null;
|
|
119
|
+
const acc = obj?.acc || obj?.['ev-acc'] || null;
|
|
62
120
|
|
|
63
121
|
// If no palette data found, return null
|
|
64
|
-
if (!main && !sec && !acc)
|
|
122
|
+
if (!main && !sec && !acc) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
65
125
|
|
|
66
126
|
// Helper: only include explicitly defined color values
|
|
67
127
|
// This ensures we don't include undefined shades in the palette
|
|
128
|
+
// Also strips 'ev-' prefix from shade names for future-proofing (to distinguish event colors from org colors)
|
|
129
|
+
// Palette keys are normalized above (ev-main -> main), shade names are normalized here (ev-main-raw -> main-raw)
|
|
68
130
|
const fill = (p: any) => {
|
|
69
131
|
if (!p || typeof p !== 'object') return {} as any;
|
|
70
132
|
const out: any = {};
|
|
@@ -75,7 +137,12 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
|
|
|
75
137
|
// Only include the key if it has a defined value (not null, undefined, or empty)
|
|
76
138
|
const value = p[key];
|
|
77
139
|
if (value !== null && value !== undefined && value !== '') {
|
|
78
|
-
|
|
140
|
+
// Strip 'ev-' prefix from shade names for future-proofing
|
|
141
|
+
// e.g., 'ev-acc-500' -> 'acc-500', 'ev-main-raw' -> 'main-raw', 'ev-sec-200' -> 'sec-200'
|
|
142
|
+
const normalizedKey = typeof key === 'string' && key.startsWith('ev-')
|
|
143
|
+
? key.substring(3)
|
|
144
|
+
: key;
|
|
145
|
+
out[normalizedKey] = value;
|
|
79
146
|
}
|
|
80
147
|
}
|
|
81
148
|
|
|
@@ -88,7 +155,6 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
|
|
|
88
155
|
acc: fill(acc)
|
|
89
156
|
};
|
|
90
157
|
} catch (error) {
|
|
91
|
-
log.warn('Failed to parse/normalize event colours:', error);
|
|
92
158
|
return null;
|
|
93
159
|
}
|
|
94
160
|
}
|
package/src/types/supabase.ts
CHANGED
|
@@ -128,7 +128,7 @@ export type RPCFunction =
|
|
|
128
128
|
| 'rbac_page_access_check'
|
|
129
129
|
| 'rbac_role_grant'
|
|
130
130
|
| 'rbac_role_revoke'
|
|
131
|
-
| '
|
|
131
|
+
| 'data_rbac_roles_list'
|
|
132
132
|
| 'rbac_role_validate'
|
|
133
133
|
| 'rbac_session_track'
|
|
134
134
|
| 'rbac_audit_log'
|
|
@@ -137,8 +137,7 @@ export type RPCFunction =
|
|
|
137
137
|
| 'data_user_organisation_roles_get'
|
|
138
138
|
| 'data_user_organisations_get'
|
|
139
139
|
| 'data_cake_meals_get'
|
|
140
|
-
|
|
141
|
-
| 'util_app_resolve'
|
|
140
|
+
| 'data_app_resolve'
|
|
142
141
|
| 'debug_auth_context'
|
|
143
142
|
| 'handle_new_user'
|
|
144
143
|
// Other functions
|
|
@@ -75,8 +75,8 @@ describe('bundleAnalysis', () => {
|
|
|
75
75
|
|
|
76
76
|
describe('bundleAnalyzer.checkTreeshaking', () => {
|
|
77
77
|
it('should do nothing in production mode', async () => {
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
// Mock import.meta.env.MODE for production using vi.stubEnv
|
|
79
|
+
vi.stubEnv('MODE', 'production');
|
|
80
80
|
|
|
81
81
|
vi.resetModules();
|
|
82
82
|
const { bundleAnalyzer } = await import('../performance/bundleAnalysis');
|
|
@@ -84,7 +84,7 @@ describe('bundleAnalysis', () => {
|
|
|
84
84
|
|
|
85
85
|
expect(consoleSpy.group).not.toHaveBeenCalled();
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
vi.unstubAllEnvs();
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
it('should log treeshaking analysis in development mode', async () => {
|
|
@@ -115,8 +115,8 @@ describe('bundleAnalysis', () => {
|
|
|
115
115
|
|
|
116
116
|
describe('bundleAnalyzer.validateExports', () => {
|
|
117
117
|
it('should do nothing in production mode', async () => {
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
// Mock import.meta.env.MODE for production using vi.stubEnv
|
|
119
|
+
vi.stubEnv('MODE', 'production');
|
|
120
120
|
|
|
121
121
|
vi.resetModules();
|
|
122
122
|
const { bundleAnalyzer } = await import('../performance/bundleAnalysis');
|
|
@@ -124,7 +124,7 @@ describe('bundleAnalysis', () => {
|
|
|
124
124
|
|
|
125
125
|
expect(consoleSpy.group).not.toHaveBeenCalled();
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
vi.unstubAllEnvs();
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
it('should log export validation in development mode', async () => {
|
|
@@ -290,8 +290,8 @@ describe('bundleAnalysis', () => {
|
|
|
290
290
|
|
|
291
291
|
describe('trackDynamicImport', () => {
|
|
292
292
|
it('should do nothing in production mode', async () => {
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
// Mock import.meta.env.MODE for production using vi.stubEnv
|
|
294
|
+
vi.stubEnv('MODE', 'production');
|
|
295
295
|
|
|
296
296
|
vi.resetModules();
|
|
297
297
|
const { trackDynamicImport } = await import('../performance/bundleAnalysis');
|
|
@@ -299,7 +299,7 @@ describe('bundleAnalysis', () => {
|
|
|
299
299
|
|
|
300
300
|
expect(consoleSpy.log).not.toHaveBeenCalled();
|
|
301
301
|
|
|
302
|
-
|
|
302
|
+
vi.unstubAllEnvs();
|
|
303
303
|
});
|
|
304
304
|
|
|
305
305
|
it('should log dynamic imports in development mode', async () => {
|