@jmruthers/pace-core 0.6.6 → 0.6.7
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} +12 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -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 +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -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 +291 -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 +241 -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-7PMH7XN7.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
- package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
- package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
- package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
- package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
- package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
- package/dist/components.d.ts +5 -4
- package/dist/components.js +27 -32
- 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 +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -17
- package/dist/rbac/index.js +6 -6
- package/dist/theming/runtime.d.ts +14 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- 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 +47 -31
- 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/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/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- 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} +204 -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 +21 -10
- package/package.json +6 -5
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +284 -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 +10 -10
- 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 +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +137 -153
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- 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 +10 -9
- 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 +41 -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 +2 -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 +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- 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__/useFocusTrap.unit.test.tsx +97 -97
- 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 +5 -5
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +1 -4
- package/src/hooks/useFileDisplay.ts +2 -2
- 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 +37 -37
- 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/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/storage/README.md +1 -1
- 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
|
@@ -58,15 +58,15 @@ const TestComponent = () => {
|
|
|
58
58
|
const auth = useUnifiedAuth();
|
|
59
59
|
|
|
60
60
|
return (
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
<
|
|
69
|
-
</
|
|
61
|
+
<section data-testid="test-component">
|
|
62
|
+
<p data-testid="hasUser">{auth.user !== null ? 'true' : 'false'}</p>
|
|
63
|
+
<p data-testid="hasSession">{auth.session !== null ? 'true' : 'false'}</p>
|
|
64
|
+
<p data-testid="hasSignIn">{typeof auth.signIn === 'function' ? 'true' : 'false'}</p>
|
|
65
|
+
<p data-testid="hasSignOut">{typeof auth.signOut === 'function' ? 'true' : 'false'}</p>
|
|
66
|
+
<p data-testid="hasOrganisation">{typeof auth.selectedOrganisation === 'object' && auth.selectedOrganisation !== null ? 'true' : 'false'}</p>
|
|
67
|
+
<p data-testid="hasEvents">{Array.isArray(auth.events) ? 'true' : 'false'}</p>
|
|
68
|
+
<p data-testid="hasAppName">{typeof auth.appName === 'string' ? 'true' : 'false'}</p>
|
|
69
|
+
</section>
|
|
70
70
|
);
|
|
71
71
|
};
|
|
72
72
|
|
|
@@ -91,7 +91,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
91
91
|
</UnifiedAuthProvider>
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
-
expect(screen.getByTestId('test-component')).
|
|
94
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
it('renders with custom app name', () => {
|
|
@@ -101,7 +101,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
101
101
|
</UnifiedAuthProvider>
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
-
expect(screen.getByTestId('test-component')).
|
|
104
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
it('renders without supabase client', () => {
|
|
@@ -111,7 +111,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
111
111
|
</UnifiedAuthProvider>
|
|
112
112
|
);
|
|
113
113
|
|
|
114
|
-
expect(screen.getByTestId('test-component')).
|
|
114
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
117
|
|
|
@@ -148,9 +148,9 @@ describe('UnifiedAuthProvider', () => {
|
|
|
148
148
|
const TestHookComponent = () => {
|
|
149
149
|
try {
|
|
150
150
|
const auth = useUnifiedAuth();
|
|
151
|
-
return <
|
|
151
|
+
return <p data-testid="hook-success">Hook works</p>;
|
|
152
152
|
} catch (error) {
|
|
153
|
-
return <
|
|
153
|
+
return <p data-testid="hook-error">Hook failed</p>;
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
156
|
|
|
@@ -160,7 +160,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
160
160
|
</UnifiedAuthProvider>
|
|
161
161
|
);
|
|
162
162
|
|
|
163
|
-
expect(screen.getByTestId('hook-success')).
|
|
163
|
+
expect(screen.getByTestId('hook-success')).toBeDefined();
|
|
164
164
|
});
|
|
165
165
|
});
|
|
166
166
|
|
|
@@ -177,7 +177,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
177
177
|
</UnifiedAuthProvider>
|
|
178
178
|
);
|
|
179
179
|
|
|
180
|
-
expect(screen.getByTestId('test-component')).
|
|
180
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
181
181
|
});
|
|
182
182
|
|
|
183
183
|
it('uses default configuration', () => {
|
|
@@ -187,7 +187,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
187
187
|
</UnifiedAuthProvider>
|
|
188
188
|
);
|
|
189
189
|
|
|
190
|
-
expect(screen.getByTestId('test-component')).
|
|
190
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
191
191
|
});
|
|
192
192
|
});
|
|
193
193
|
|
|
@@ -197,12 +197,12 @@ describe('UnifiedAuthProvider', () => {
|
|
|
197
197
|
const auth = useUnifiedAuth();
|
|
198
198
|
|
|
199
199
|
return (
|
|
200
|
-
<
|
|
201
|
-
<
|
|
202
|
-
<
|
|
200
|
+
<section>
|
|
201
|
+
<p data-testid="composition-success">composed</p>
|
|
202
|
+
<p data-testid="has-all-contexts">
|
|
203
203
|
{auth.user && auth.session && auth.isAuthenticated ? 'yes' : 'no'}
|
|
204
|
-
</
|
|
205
|
-
</
|
|
204
|
+
</p>
|
|
205
|
+
</section>
|
|
206
206
|
);
|
|
207
207
|
};
|
|
208
208
|
|
|
@@ -225,13 +225,13 @@ describe('UnifiedAuthProvider', () => {
|
|
|
225
225
|
const auth = useUnifiedAuth();
|
|
226
226
|
|
|
227
227
|
return (
|
|
228
|
-
<
|
|
229
|
-
<
|
|
230
|
-
<
|
|
231
|
-
<
|
|
232
|
-
<
|
|
233
|
-
<
|
|
234
|
-
</
|
|
228
|
+
<section>
|
|
229
|
+
<p data-testid="user-context">{auth.user ? 'present' : 'missing'}</p>
|
|
230
|
+
<p data-testid="session-context">{auth.session ? 'present' : 'missing'}</p>
|
|
231
|
+
<p data-testid="organisation-context">{auth.selectedOrganisation ? 'present' : 'missing'}</p>
|
|
232
|
+
<p data-testid="event-context">{auth.selectedEvent ? 'missing' : 'present'}</p>
|
|
233
|
+
<p data-testid="app-context">{auth.appName ? 'present' : 'missing'}</p>
|
|
234
|
+
</section>
|
|
235
235
|
);
|
|
236
236
|
};
|
|
237
237
|
|
|
@@ -258,10 +258,10 @@ describe('UnifiedAuthProvider', () => {
|
|
|
258
258
|
const auth = useUnifiedAuth();
|
|
259
259
|
|
|
260
260
|
return (
|
|
261
|
-
<
|
|
262
|
-
<
|
|
263
|
-
<
|
|
264
|
-
</
|
|
261
|
+
<section>
|
|
262
|
+
<p data-testid="provider-hierarchy">valid</p>
|
|
263
|
+
<p data-testid="auth-available">{auth ? 'yes' : 'no'}</p>
|
|
264
|
+
</section>
|
|
265
265
|
);
|
|
266
266
|
};
|
|
267
267
|
|
|
@@ -282,14 +282,14 @@ describe('UnifiedAuthProvider', () => {
|
|
|
282
282
|
const auth = useUnifiedAuth();
|
|
283
283
|
|
|
284
284
|
return (
|
|
285
|
-
<
|
|
286
|
-
<
|
|
285
|
+
<section>
|
|
286
|
+
<p data-testid="loading-orchestration">
|
|
287
287
|
{auth.isLoading ? 'loading' : 'ready'}
|
|
288
|
-
</
|
|
289
|
-
<
|
|
288
|
+
</p>
|
|
289
|
+
<p data-testid="context-ready">
|
|
290
290
|
{auth.user && auth.session ? 'ready' : 'initializing'}
|
|
291
|
-
</
|
|
292
|
-
</
|
|
291
|
+
</p>
|
|
292
|
+
</section>
|
|
293
293
|
);
|
|
294
294
|
};
|
|
295
295
|
|
|
@@ -299,8 +299,8 @@ describe('UnifiedAuthProvider', () => {
|
|
|
299
299
|
</UnifiedAuthProvider>
|
|
300
300
|
);
|
|
301
301
|
|
|
302
|
-
expect(screen.getByTestId('loading-orchestration')).
|
|
303
|
-
expect(screen.getByTestId('context-ready')).
|
|
302
|
+
expect(screen.getByTestId('loading-orchestration')).toBeDefined();
|
|
303
|
+
expect(screen.getByTestId('context-ready')).toBeDefined();
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
it('coordinates loading across multiple context sources', () => {
|
|
@@ -308,12 +308,12 @@ describe('UnifiedAuthProvider', () => {
|
|
|
308
308
|
const auth = useUnifiedAuth();
|
|
309
309
|
|
|
310
310
|
return (
|
|
311
|
-
<
|
|
312
|
-
<
|
|
313
|
-
<
|
|
311
|
+
<section>
|
|
312
|
+
<p data-testid="coordination">{auth.isLoading ? 'coordinating' : 'coordinated'}</p>
|
|
313
|
+
<p data-testid="all-contexts-loaded">
|
|
314
314
|
{auth.user && auth.session && !auth.isLoading ? 'loaded' : 'loading'}
|
|
315
|
-
</
|
|
316
|
-
</
|
|
315
|
+
</p>
|
|
316
|
+
</section>
|
|
317
317
|
);
|
|
318
318
|
};
|
|
319
319
|
|
|
@@ -323,8 +323,8 @@ describe('UnifiedAuthProvider', () => {
|
|
|
323
323
|
</UnifiedAuthProvider>
|
|
324
324
|
);
|
|
325
325
|
|
|
326
|
-
expect(screen.getByTestId('coordination')).
|
|
327
|
-
expect(screen.getByTestId('all-contexts-loaded')).
|
|
326
|
+
expect(screen.getByTestId('coordination')).toBeDefined();
|
|
327
|
+
expect(screen.getByTestId('all-contexts-loaded')).toBeDefined();
|
|
328
328
|
});
|
|
329
329
|
});
|
|
330
330
|
|
|
@@ -334,12 +334,12 @@ describe('UnifiedAuthProvider', () => {
|
|
|
334
334
|
const auth = useUnifiedAuth();
|
|
335
335
|
|
|
336
336
|
return (
|
|
337
|
-
<
|
|
338
|
-
<
|
|
339
|
-
<
|
|
337
|
+
<section>
|
|
338
|
+
<p data-testid="error-state">{auth.error ? 'has-error' : 'no-error'}</p>
|
|
339
|
+
<p data-testid="still-functional">
|
|
340
340
|
{auth.user || auth.session ? 'functional' : 'broken'}
|
|
341
|
-
</
|
|
342
|
-
</
|
|
341
|
+
</p>
|
|
342
|
+
</section>
|
|
343
343
|
);
|
|
344
344
|
};
|
|
345
345
|
|
|
@@ -349,8 +349,8 @@ describe('UnifiedAuthProvider', () => {
|
|
|
349
349
|
</UnifiedAuthProvider>
|
|
350
350
|
);
|
|
351
351
|
|
|
352
|
-
expect(screen.getByTestId('error-state')).
|
|
353
|
-
expect(screen.getByTestId('still-functional')).
|
|
352
|
+
expect(screen.getByTestId('error-state')).toBeDefined();
|
|
353
|
+
expect(screen.getByTestId('still-functional')).toBeDefined();
|
|
354
354
|
});
|
|
355
355
|
|
|
356
356
|
it('provides error recovery mechanisms', () => {
|
|
@@ -358,12 +358,12 @@ describe('UnifiedAuthProvider', () => {
|
|
|
358
358
|
const auth = useUnifiedAuth();
|
|
359
359
|
|
|
360
360
|
return (
|
|
361
|
-
<
|
|
362
|
-
<
|
|
361
|
+
<section>
|
|
362
|
+
<p data-testid="recovery-available">
|
|
363
363
|
{auth.refreshSession ? 'available' : 'unavailable'}
|
|
364
|
-
</
|
|
365
|
-
<
|
|
366
|
-
</
|
|
364
|
+
</p>
|
|
365
|
+
<p data-testid="error-handled">{auth.error ? 'handled' : 'no-error'}</p>
|
|
366
|
+
</section>
|
|
367
367
|
);
|
|
368
368
|
};
|
|
369
369
|
|
|
@@ -373,8 +373,8 @@ describe('UnifiedAuthProvider', () => {
|
|
|
373
373
|
</UnifiedAuthProvider>
|
|
374
374
|
);
|
|
375
375
|
|
|
376
|
-
expect(screen.getByTestId('recovery-available')).
|
|
377
|
-
expect(screen.getByTestId('error-handled')).
|
|
376
|
+
expect(screen.getByTestId('recovery-available')).toBeDefined();
|
|
377
|
+
expect(screen.getByTestId('error-handled')).toBeDefined();
|
|
378
378
|
});
|
|
379
379
|
|
|
380
380
|
it('maintains stability during error states', () => {
|
|
@@ -382,12 +382,12 @@ describe('UnifiedAuthProvider', () => {
|
|
|
382
382
|
const auth = useUnifiedAuth();
|
|
383
383
|
|
|
384
384
|
return (
|
|
385
|
-
<
|
|
386
|
-
<
|
|
385
|
+
<section>
|
|
386
|
+
<p data-testid="stable-during-error">
|
|
387
387
|
{auth ? 'stable' : 'unstable'}
|
|
388
|
-
</
|
|
389
|
-
<
|
|
390
|
-
</
|
|
388
|
+
</p>
|
|
389
|
+
<p data-testid="re-render-safe">safe</p>
|
|
390
|
+
</section>
|
|
391
391
|
);
|
|
392
392
|
};
|
|
393
393
|
|
|
@@ -397,7 +397,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
397
397
|
</UnifiedAuthProvider>
|
|
398
398
|
);
|
|
399
399
|
|
|
400
|
-
expect(screen.getByTestId('stable-during-error')).
|
|
400
|
+
expect(screen.getByTestId('stable-during-error')).toBeDefined();
|
|
401
401
|
|
|
402
402
|
// Re-render during error state
|
|
403
403
|
rerender(
|
|
@@ -416,14 +416,14 @@ describe('UnifiedAuthProvider', () => {
|
|
|
416
416
|
const auth = useUnifiedAuth();
|
|
417
417
|
|
|
418
418
|
return (
|
|
419
|
-
<
|
|
420
|
-
<
|
|
419
|
+
<section>
|
|
420
|
+
<p data-testid="hook-access">
|
|
421
421
|
{auth.user && auth.session && auth.isAuthenticated ? 'full' : 'partial'}
|
|
422
|
-
</
|
|
423
|
-
<
|
|
422
|
+
</p>
|
|
423
|
+
<p data-testid="hook-methods">
|
|
424
424
|
{auth.signIn && auth.signOut && auth.refreshSession ? 'complete' : 'incomplete'}
|
|
425
|
-
</
|
|
426
|
-
</
|
|
425
|
+
</p>
|
|
426
|
+
</section>
|
|
427
427
|
);
|
|
428
428
|
};
|
|
429
429
|
|
|
@@ -447,12 +447,12 @@ describe('UnifiedAuthProvider', () => {
|
|
|
447
447
|
const auth = useUnifiedAuth();
|
|
448
448
|
|
|
449
449
|
return (
|
|
450
|
-
<
|
|
451
|
-
<
|
|
452
|
-
<
|
|
450
|
+
<section>
|
|
451
|
+
<p data-testid="user-stable">{auth.user ? 'stable' : 'unstable'}</p>
|
|
452
|
+
<p data-testid="methods-stable">
|
|
453
453
|
{auth.signIn && auth.signOut ? 'stable' : 'unstable'}
|
|
454
|
-
</
|
|
455
|
-
</
|
|
454
|
+
</p>
|
|
455
|
+
</section>
|
|
456
456
|
);
|
|
457
457
|
};
|
|
458
458
|
|
|
@@ -486,10 +486,10 @@ describe('UnifiedAuthProvider', () => {
|
|
|
486
486
|
const isAuthenticated = auth.isAuthenticated;
|
|
487
487
|
|
|
488
488
|
return (
|
|
489
|
-
<
|
|
490
|
-
<
|
|
491
|
-
<
|
|
492
|
-
</
|
|
489
|
+
<section>
|
|
490
|
+
<p data-testid="concurrent-safe">safe</p>
|
|
491
|
+
<p data-testid="all-reads">{user && session && isAuthenticated ? 'success' : 'fail'}</p>
|
|
492
|
+
</section>
|
|
493
493
|
);
|
|
494
494
|
};
|
|
495
495
|
|
|
@@ -514,13 +514,13 @@ describe('UnifiedAuthProvider', () => {
|
|
|
514
514
|
const auth = useUnifiedAuth();
|
|
515
515
|
|
|
516
516
|
return (
|
|
517
|
-
<
|
|
518
|
-
<
|
|
519
|
-
<
|
|
520
|
-
<
|
|
517
|
+
<section>
|
|
518
|
+
<p data-testid="custom-app-name">{auth.appName}</p>
|
|
519
|
+
<p data-testid="app-name-present">{auth.appName ? 'present' : 'missing'}</p>
|
|
520
|
+
<p data-testid="app-name-consistent">
|
|
521
521
|
{auth.appName && auth.appName.length > 0 ? 'consistent' : 'inconsistent'}
|
|
522
|
-
</
|
|
523
|
-
</
|
|
522
|
+
</p>
|
|
523
|
+
</section>
|
|
524
524
|
);
|
|
525
525
|
};
|
|
526
526
|
|
|
@@ -542,14 +542,14 @@ describe('UnifiedAuthProvider', () => {
|
|
|
542
542
|
const auth = useUnifiedAuth();
|
|
543
543
|
|
|
544
544
|
return (
|
|
545
|
-
<
|
|
546
|
-
<
|
|
545
|
+
<section>
|
|
546
|
+
<p data-testid="rbac-enabled">
|
|
547
547
|
{auth.isAuthenticated ? 'enabled' : 'disabled'}
|
|
548
|
-
</
|
|
549
|
-
<
|
|
548
|
+
</p>
|
|
549
|
+
<p data-testid="session-available">
|
|
550
550
|
{auth.session ? 'available' : 'unavailable'}
|
|
551
|
-
</
|
|
552
|
-
</
|
|
551
|
+
</p>
|
|
552
|
+
</section>
|
|
553
553
|
);
|
|
554
554
|
};
|
|
555
555
|
|
|
@@ -564,7 +564,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
564
564
|
expect(screen.getByTestId('rbac-enabled')).toHaveTextContent('enabled');
|
|
565
565
|
}, { timeout: 3000 });
|
|
566
566
|
|
|
567
|
-
expect(screen.getByTestId('session-available')).
|
|
567
|
+
expect(screen.getByTestId('session-available')).toBeDefined();
|
|
568
568
|
});
|
|
569
569
|
|
|
570
570
|
it('configures inactivity tracking when enabled', () => {
|
|
@@ -572,14 +572,14 @@ describe('UnifiedAuthProvider', () => {
|
|
|
572
572
|
const auth = useUnifiedAuth();
|
|
573
573
|
|
|
574
574
|
return (
|
|
575
|
-
<
|
|
576
|
-
<
|
|
575
|
+
<section>
|
|
576
|
+
<p data-testid="inactivity-config">
|
|
577
577
|
{auth.isLoading ? 'configuring' : 'configured'}
|
|
578
|
-
</
|
|
579
|
-
<
|
|
578
|
+
</p>
|
|
579
|
+
<p data-testid="context-complete">
|
|
580
580
|
{auth.user && auth.session ? 'complete' : 'incomplete'}
|
|
581
|
-
</
|
|
582
|
-
</
|
|
581
|
+
</p>
|
|
582
|
+
</section>
|
|
583
583
|
);
|
|
584
584
|
};
|
|
585
585
|
|
|
@@ -589,7 +589,7 @@ describe('UnifiedAuthProvider', () => {
|
|
|
589
589
|
</UnifiedAuthProvider>
|
|
590
590
|
);
|
|
591
591
|
|
|
592
|
-
expect(screen.getByTestId('inactivity-config')).
|
|
592
|
+
expect(screen.getByTestId('inactivity-config')).toBeDefined();
|
|
593
593
|
expect(screen.getByTestId('context-complete')).toHaveTextContent('complete');
|
|
594
594
|
});
|
|
595
595
|
});
|
|
@@ -67,12 +67,12 @@ function TestComponent() {
|
|
|
67
67
|
}, [authService]);
|
|
68
68
|
|
|
69
69
|
return (
|
|
70
|
-
<
|
|
71
|
-
<
|
|
72
|
-
<
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
</
|
|
70
|
+
<section>
|
|
71
|
+
<p data-testid="user-id">{authService.getUser()?.id || 'no-user'}</p>
|
|
72
|
+
<p data-testid="is-authenticated">{authService.isAuthenticated().toString()}</p>
|
|
73
|
+
<p data-testid="is-loading">{authService.isLoading().toString()}</p>
|
|
74
|
+
<p data-testid="error">{authService.getError()?.message || 'no-error'}</p>
|
|
75
|
+
</section>
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -198,7 +198,7 @@ describe('AuthServiceProvider Integration', () => {
|
|
|
198
198
|
// The subscription is set up in useEffect, so we need to wait for that
|
|
199
199
|
await waitFor(() => {
|
|
200
200
|
// Check if subscription is set up by verifying the component has rendered
|
|
201
|
-
expect(screen.getByTestId('user-id')).
|
|
201
|
+
expect(screen.getByTestId('user-id')).toBeDefined();
|
|
202
202
|
}, { interval: 10, timeout: 1000 });
|
|
203
203
|
|
|
204
204
|
// Wait a bit more to ensure subscription is fully set up
|
|
@@ -61,16 +61,16 @@ function TestComponent() {
|
|
|
61
61
|
const auth = useUnifiedAuth();
|
|
62
62
|
|
|
63
63
|
return (
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
<
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
<
|
|
72
|
-
<
|
|
73
|
-
</
|
|
64
|
+
<section>
|
|
65
|
+
<p data-testid="user-id">{auth.user?.id || 'no-user'}</p>
|
|
66
|
+
<p data-testid="is-authenticated">{auth.isAuthenticated.toString()}</p>
|
|
67
|
+
<p data-testid="is-loading">{auth.isLoading.toString()}</p>
|
|
68
|
+
<p data-testid="app-name">{auth.appName}</p>
|
|
69
|
+
<p data-testid="permissions-count">{0}</p>
|
|
70
|
+
<p data-testid="roles-count">{0}</p>
|
|
71
|
+
<p data-testid="organisations-count">{auth.organisations.length}</p>
|
|
72
|
+
<p data-testid="events-count">{auth.events.length}</p>
|
|
73
|
+
</section>
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|
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('normalizes legacy format with ev-main, ev-sec, ev-acc keys to standard format', () => {
|
|
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,14 @@ describe('parseAndNormalizeEventColours', () => {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
const result = parseAndNormalizeEventColours(input);
|
|
99
|
-
// Legacy format is
|
|
100
|
-
expect(result).toBeNull();
|
|
99
|
+
// Legacy format is normalized to standard format (ev-main -> main, etc.)
|
|
100
|
+
expect(result).not.toBeNull();
|
|
101
|
+
expect(result).toHaveProperty('main');
|
|
102
|
+
expect(result).toHaveProperty('sec');
|
|
103
|
+
expect(result).toHaveProperty('acc');
|
|
104
|
+
expect(result?.main).toHaveProperty('500');
|
|
105
|
+
expect(result?.sec).toHaveProperty('500');
|
|
106
|
+
expect(result?.acc).toHaveProperty('500');
|
|
101
107
|
});
|
|
102
108
|
|
|
103
109
|
it('uses standard keys when provided', () => {
|
|
@@ -8,15 +8,13 @@
|
|
|
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)
|
|
20
18
|
* - JSON string that will be parsed
|
|
21
19
|
*
|
|
22
20
|
* Only includes explicitly defined color values. Does not fill
|
|
@@ -38,6 +36,18 @@ const log = createLogger('ParseEventColours');
|
|
|
38
36
|
* // Returns: { main: { 500: {...}, raw: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
|
|
39
37
|
* ```
|
|
40
38
|
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* // Database format with ev- prefix
|
|
42
|
+
* const colours = {
|
|
43
|
+
* 'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
|
|
44
|
+
* 'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
|
|
45
|
+
* 'ev-acc': { 500: { L: 0.5, C: 0.2, H: 240 } }
|
|
46
|
+
* };
|
|
47
|
+
* const palette = parseAndNormalizeEventColours(colours);
|
|
48
|
+
* // Returns: { main: { 500: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
41
51
|
*/
|
|
42
52
|
export function parseAndNormalizeEventColours(input: unknown): { main: any; sec: any; acc: any } | null {
|
|
43
53
|
try {
|
|
@@ -55,13 +65,16 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
|
|
|
55
65
|
return null;
|
|
56
66
|
}
|
|
57
67
|
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
68
|
+
// Support both standard keys (main/sec/acc) and prefixed keys (ev-main/ev-sec/ev-acc)
|
|
69
|
+
// Database may store with ev-* prefix, but we normalize to standard keys
|
|
70
|
+
const main = obj?.main || obj?.['ev-main'] || null;
|
|
71
|
+
const sec = obj?.sec || obj?.['ev-sec'] || null;
|
|
72
|
+
const acc = obj?.acc || obj?.['ev-acc'] || null;
|
|
62
73
|
|
|
63
74
|
// If no palette data found, return null
|
|
64
|
-
if (!main && !sec && !acc)
|
|
75
|
+
if (!main && !sec && !acc) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
65
78
|
|
|
66
79
|
// Helper: only include explicitly defined color values
|
|
67
80
|
// This ensures we don't include undefined shades in the palette
|
|
@@ -88,7 +101,6 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
|
|
|
88
101
|
acc: fill(acc)
|
|
89
102
|
};
|
|
90
103
|
} catch (error) {
|
|
91
|
-
log.warn('Failed to parse/normalize event colours:', error);
|
|
92
104
|
return null;
|
|
93
105
|
}
|
|
94
106
|
}
|