@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.
Files changed (292) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +240 -0
  4. package/audit-tool/audits/03-architecture.cjs +224 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +554 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +295 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +380 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-6RMSCQJ6.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
  28. package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
  29. package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
  30. package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
  31. package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
  32. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  33. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  34. package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
  35. package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
  36. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  37. package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
  38. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  39. package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
  40. package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
  41. package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
  42. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  43. package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
  44. package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
  45. package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
  46. package/dist/components.d.ts +5 -4
  47. package/dist/components.js +29 -34
  48. package/dist/eslint-rules/index.cjs +22 -9
  49. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  50. package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
  51. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  52. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
  53. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
  54. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  55. package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
  56. package/dist/hooks.d.ts +5 -5
  57. package/dist/hooks.js +8 -8
  58. package/dist/index.d.ts +7 -7
  59. package/dist/index.js +21 -20
  60. package/dist/providers.js +2 -2
  61. package/dist/rbac/index.d.ts +1 -1
  62. package/dist/rbac/index.js +8 -8
  63. package/dist/theming/runtime.d.ts +61 -1
  64. package/dist/theming/runtime.js +1 -1
  65. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  66. package/dist/types.d.ts +2 -2
  67. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  68. package/dist/utils.d.ts +2 -2
  69. package/dist/utils.js +8 -8
  70. package/docs/README.md +1 -1
  71. package/docs/api/modules.md +106 -41
  72. package/docs/api-reference/components.md +18 -20
  73. package/docs/api-reference/hooks.md +80 -80
  74. package/docs/api-reference/types.md +1 -1
  75. package/docs/api-reference/utilities.md +1 -1
  76. package/docs/architecture/README.md +1 -1
  77. package/docs/core-concepts/events.md +3 -3
  78. package/docs/core-concepts/organisations.md +6 -6
  79. package/docs/core-concepts/permissions.md +6 -6
  80. package/docs/documentation-index.md +12 -18
  81. package/docs/getting-started/dependencies.md +23 -0
  82. package/docs/getting-started/documentation-index.md +1 -1
  83. package/docs/getting-started/examples/README.md +4 -4
  84. package/docs/getting-started/examples/full-featured-app.md +1 -1
  85. package/docs/getting-started/faq.md +2 -2
  86. package/docs/getting-started/quick-reference.md +4 -4
  87. package/docs/implementation-guides/app-layout.md +1 -1
  88. package/docs/implementation-guides/authentication.md +15 -15
  89. package/docs/implementation-guides/component-styling.md +1 -1
  90. package/docs/implementation-guides/data-tables.md +127 -34
  91. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  92. package/docs/implementation-guides/dynamic-colors.md +3 -3
  93. package/docs/implementation-guides/file-upload-storage.md +2 -2
  94. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  95. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  96. package/docs/implementation-guides/large-datasets.md +3 -2
  97. package/docs/implementation-guides/organisation-security.md +2 -2
  98. package/docs/implementation-guides/performance.md +2 -2
  99. package/docs/implementation-guides/permission-enforcement.md +1 -1
  100. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  101. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  102. package/docs/rbac/README.md +5 -5
  103. package/docs/rbac/advanced-patterns.md +6 -6
  104. package/docs/rbac/api-reference.md +20 -20
  105. package/docs/rbac/event-based-apps.md +3 -3
  106. package/docs/rbac/examples.md +41 -41
  107. package/docs/rbac/getting-started.md +37 -37
  108. package/docs/rbac/performance.md +1 -1
  109. package/docs/rbac/quick-start.md +52 -52
  110. package/docs/rbac/secure-client-protection.md +1 -1
  111. package/docs/rbac/troubleshooting.md +1 -1
  112. package/docs/security/README.md +5 -5
  113. package/docs/standards/0-standards-overview.md +220 -0
  114. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
  115. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  116. package/docs/standards/3-architecture-standards.md +606 -0
  117. package/docs/standards/4-code-quality-standards.md +728 -0
  118. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  119. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  120. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  121. package/docs/standards/8-testing-documentation-standards.md +401 -0
  122. package/docs/standards/9-operations-standards.md +1102 -0
  123. package/docs/standards/README.md +203 -104
  124. package/docs/troubleshooting/README.md +4 -4
  125. package/docs/troubleshooting/common-issues.md +2 -2
  126. package/docs/troubleshooting/debugging.md +9 -9
  127. package/docs/troubleshooting/migration.md +4 -4
  128. package/eslint-config-pace-core.cjs +50 -20
  129. package/package.json +50 -19
  130. package/scripts/eslint-audit.cjs +123 -0
  131. package/scripts/install-cursor-rules.cjs +11 -243
  132. package/scripts/install-eslint-config.cjs +349 -0
  133. package/scripts/validate-dependencies.cjs +248 -0
  134. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  135. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  136. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
  137. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  138. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  139. package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
  140. package/src/__tests__/templates/component.test.template.tsx +18 -15
  141. package/src/components/AddressField/AddressField.tsx +26 -1
  142. package/src/components/Alert/Alert.test.tsx +86 -22
  143. package/src/components/Alert/Alert.tsx +19 -11
  144. package/src/components/Badge/Badge.tsx +1 -1
  145. package/src/components/Calendar/Calendar.tsx +201 -47
  146. package/src/components/Checkbox/Checkbox.test.tsx +2 -1
  147. package/src/components/ContextSelector/ContextSelector.tsx +108 -126
  148. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  149. package/src/components/DataTable/DataTable.tsx +1 -19
  150. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
  151. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
  152. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
  153. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  154. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  155. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  156. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  157. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  158. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  159. package/src/components/DataTable/components/EmptyState.tsx +11 -10
  160. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  161. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  162. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  163. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  164. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  165. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  166. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  167. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  168. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  169. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
  170. package/src/components/DataTable/components/index.ts +2 -1
  171. package/src/components/DataTable/types.ts +0 -18
  172. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  173. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
  174. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  175. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  176. package/src/components/Dialog/Dialog.test.tsx +1 -0
  177. package/src/components/Dialog/Dialog.tsx +25 -8
  178. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  179. package/src/components/FileUpload/FileUpload.test.tsx +45 -16
  180. package/src/components/FileUpload/FileUpload.tsx +141 -130
  181. package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
  182. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
  183. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
  184. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
  185. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
  186. package/src/components/Progress/Progress.tsx +2 -4
  187. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  188. package/src/components/Select/Select.tsx +86 -77
  189. package/src/components/Select/types.ts +3 -0
  190. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  191. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  192. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
  193. package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
  194. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
  195. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
  196. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
  197. package/src/hooks/public/usePublicEvent.ts +5 -5
  198. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  199. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  200. package/src/hooks/public/usePublicRouteParams.ts +13 -9
  201. package/src/hooks/useAddressAutocomplete.test.ts +18 -18
  202. package/src/hooks/useAppConfig.ts +2 -2
  203. package/src/hooks/useEventTheme.test.ts +7 -7
  204. package/src/hooks/useEventTheme.ts +2 -1
  205. package/src/hooks/useFileDisplay.ts +2 -2
  206. package/src/hooks/useFileUrl.ts +52 -8
  207. package/src/hooks/useOrganisationSecurity.test.ts +2 -1
  208. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  209. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  210. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  211. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  212. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  213. package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
  214. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  215. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  216. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  217. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
  218. package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
  219. package/src/rbac/api.test.ts +104 -0
  220. package/src/rbac/engine.ts +1 -1
  221. package/src/rbac/hooks/useCan.test.ts +2 -2
  222. package/src/rbac/secureClient.ts +1 -1
  223. package/src/rbac/types/functions.ts +1 -1
  224. package/src/styles/core.css +7 -0
  225. package/src/theming/__tests__/parseEventColours.test.ts +118 -3
  226. package/src/theming/parseEventColours.ts +77 -11
  227. package/src/types/supabase.ts +2 -3
  228. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
  229. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  230. package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
  231. package/src/utils/formatting/formatDate.test.ts +3 -2
  232. package/src/utils/formatting/formatDateTime.test.ts +2 -2
  233. package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
  234. package/src/utils/storage/README.md +1 -1
  235. package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
  236. package/src/utils/storage/helpers.test.ts +69 -3
  237. package/cursor-rules/01-standards-compliance.mdc +0 -285
  238. package/cursor-rules/04-testing-standards.mdc +0 -270
  239. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  240. package/cursor-rules/06-code-quality.mdc +0 -311
  241. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  242. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  243. package/cursor-rules/11-performance-optimization.mdc +0 -169
  244. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  245. package/dist/DataTable-LRJL4IRV.js +0 -15
  246. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  247. package/dist/eslint-rules/rules/components.cjs +0 -113
  248. package/dist/eslint-rules/rules/imports.cjs +0 -102
  249. package/docs/best-practices/README.md +0 -472
  250. package/docs/best-practices/accessibility.md +0 -604
  251. package/docs/best-practices/common-patterns.md +0 -516
  252. package/docs/best-practices/deployment.md +0 -1103
  253. package/docs/best-practices/performance.md +0 -1328
  254. package/docs/best-practices/security.md +0 -940
  255. package/docs/best-practices/testing.md +0 -1034
  256. package/docs/rbac/compliance/compliance-guide.md +0 -544
  257. package/docs/standards/01-standards-compliance.md +0 -188
  258. package/docs/standards/03-solid-principles.md +0 -39
  259. package/docs/standards/04-testing-standards.md +0 -36
  260. package/docs/standards/05-bug-reports-and-features.md +0 -27
  261. package/docs/standards/06-code-quality.md +0 -34
  262. package/docs/standards/07-tech-stack-compliance.md +0 -30
  263. package/docs/standards/10-error-handling-patterns.md +0 -401
  264. package/docs/standards/11-performance-optimization.md +0 -348
  265. package/docs/standards/12-ci-cd-integration.md +0 -370
  266. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  267. package/scripts/audit/audit-compliance.cjs +0 -1295
  268. package/scripts/audit/audit-components.cjs +0 -260
  269. package/scripts/audit/audit-rbac.cjs +0 -954
  270. package/scripts/audit/audit-standards.cjs +0 -1268
  271. package/scripts/audit/index.cjs +0 -1927
  272. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  273. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  274. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  275. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  276. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  277. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  278. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  279. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  280. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  281. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  282. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  284. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  285. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  286. package/src/components/DataTable/utils/debugTools.ts +0 -514
  287. package/src/eslint-rules/index.cjs +0 -22
  288. package/src/eslint-rules/rules/components.cjs +0 -113
  289. package/src/eslint-rules/rules/imports.cjs +0 -102
  290. package/src/eslint-rules/rules/rbac.cjs +0 -790
  291. package/src/eslint-rules/utils/helpers.cjs +0 -42
  292. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -1,514 +0,0 @@
1
- /**
2
- * @file Advanced Debugging Tools for DataTable Performance
3
- * @package @jmruthers/pace-core
4
- * @module Components/DataTable/Utils/DebugTools
5
- * @since 0.3.0
6
- */
7
-
8
- import React from 'react';
9
- import type {
10
- DataRecord,
11
- PaginationMode,
12
- ServerSideParams
13
- } from '../types';
14
- import { createLogger } from '../../../utils/core/logger';
15
-
16
- /**
17
- * Debug levels for controlling verbosity (internal use only)
18
- */
19
- enum DebugLevel {
20
- NONE = 0,
21
- ERROR = 1,
22
- WARN = 2,
23
- INFO = 3,
24
- DEBUG = 4,
25
- TRACE = 5,
26
- }
27
-
28
- /**
29
- * Performance debug configuration (internal use only)
30
- */
31
- interface DebugConfig {
32
- enabled: boolean;
33
- level: DebugLevel;
34
- logToConsole: boolean;
35
- logToStorage: boolean;
36
- maxLogEntries: number;
37
- enablePerformanceMarks: boolean;
38
- enableMemoryTracking: boolean;
39
- enableRenderTracking: boolean;
40
- enableNetworkTracking: boolean;
41
- }
42
-
43
- /**
44
- * Default debug configuration (internal use only)
45
- */
46
- const DEFAULT_DEBUG_CONFIG: DebugConfig = {
47
- enabled: import.meta.env.MODE === 'development',
48
- level: DebugLevel.INFO,
49
- logToConsole: true,
50
- logToStorage: false,
51
- maxLogEntries: 1000,
52
- enablePerformanceMarks: true,
53
- enableMemoryTracking: true,
54
- enableRenderTracking: true,
55
- enableNetworkTracking: true,
56
- };
57
-
58
- /**
59
- * Debug log entry interface (internal use only)
60
- */
61
- interface DebugLogEntry {
62
- timestamp: number;
63
- level: DebugLevel;
64
- category: string;
65
- message: string;
66
- data?: unknown;
67
- stackTrace?: string;
68
- performanceMarks?: string[];
69
- memoryUsage?: number;
70
- }
71
-
72
- /**
73
- * Performance timeline entry (internal use only)
74
- */
75
- interface PerformanceTimelineEntry {
76
- id: string;
77
- operation: string;
78
- startTime: number;
79
- endTime?: number;
80
- duration?: number;
81
- metadata?: Record<string, unknown>;
82
- children?: PerformanceTimelineEntry[];
83
- }
84
-
85
- /**
86
- * Memory snapshot (internal use only)
87
- */
88
- interface MemorySnapshot {
89
- timestamp: number;
90
- heapUsed: number;
91
- heapTotal: number;
92
- external: number;
93
- arrayBuffers?: number;
94
- }
95
-
96
- /**
97
- * Render performance data (internal use only)
98
- */
99
- interface RenderPerformanceData {
100
- componentName: string;
101
- renderCount: number;
102
- totalRenderTime: number;
103
- averageRenderTime: number;
104
- lastRenderTime: number;
105
- propsChanges: number;
106
- }
107
-
108
- /**
109
- * Advanced DataTable debugger (internal use only)
110
- */
111
- class DataTableDebugger {
112
- private config: DebugConfig
113
- private logger = createLogger('DataTableDebugger');
114
- private logEntries: DebugLogEntry[] = [];
115
- private performanceTimeline: Map<string, PerformanceTimelineEntry> = new Map();
116
- private memorySnapshots: MemorySnapshot[] = [];
117
- private renderPerformance: Map<string, RenderPerformanceData> = new Map();
118
- private activeOperations: Set<string> = new Set();
119
-
120
- constructor(config: Partial<DebugConfig> = {}) {
121
- this.config = { ...DEFAULT_DEBUG_CONFIG, ...config };
122
- }
123
-
124
- /**
125
- * Log a debug message
126
- */
127
- log(
128
- level: DebugLevel,
129
- category: string,
130
- message: string,
131
- data?: unknown,
132
- includeStackTrace: boolean = false
133
- ): void {
134
- if (!this.config.enabled || level > this.config.level) {
135
- return;
136
- }
137
-
138
- const entry: DebugLogEntry = {
139
- timestamp: Date.now(),
140
- level,
141
- category,
142
- message,
143
- data,
144
- stackTrace: includeStackTrace ? new Error().stack : undefined,
145
- memoryUsage: this.config.enableMemoryTracking ? this.getCurrentMemoryUsage() : undefined,
146
- };
147
-
148
- this.logEntries.push(entry);
149
-
150
- // Maintain log size
151
- if (this.logEntries.length > this.config.maxLogEntries) {
152
- this.logEntries.shift();
153
- }
154
-
155
- // Console logging
156
- if (this.config.logToConsole) {
157
- this.logToConsole(entry);
158
- }
159
-
160
- // Storage logging
161
- if (this.config.logToStorage) {
162
- this.logToStorage(entry);
163
- }
164
- }
165
-
166
- /**
167
- * Start performance tracking for an operation
168
- */
169
- startOperation(operationId: string, operation: string, metadata?: Record<string, unknown>): void {
170
- if (!this.config.enabled || !this.config.enableRenderTracking) return;
171
-
172
- const entry: PerformanceTimelineEntry = {
173
- id: operationId,
174
- operation,
175
- startTime: performance.now(),
176
- metadata,
177
- children: [],
178
- };
179
-
180
- this.performanceTimeline.set(operationId, entry);
181
- this.activeOperations.add(operationId);
182
-
183
- // Performance marks
184
- if (this.config.enablePerformanceMarks) {
185
- performance.mark(`${operationId}_start`);
186
- }
187
-
188
- this.log(DebugLevel.DEBUG, 'Performance', `Started operation: ${operation}`, { operationId, metadata });
189
- }
190
-
191
- /**
192
- * End performance tracking for an operation
193
- */
194
- endOperation(operationId: string, metadata?: Record<string, unknown>): void {
195
- if (!this.config.enabled || !this.config.enableRenderTracking) return;
196
-
197
- const entry = this.performanceTimeline.get(operationId);
198
- if (!entry) {
199
- this.log(DebugLevel.WARN, 'Performance', `Operation not found: ${operationId}`);
200
- return;
201
- }
202
-
203
- entry.endTime = performance.now();
204
- entry.duration = entry.endTime - entry.startTime;
205
- if (metadata) {
206
- entry.metadata = { ...entry.metadata, ...metadata };
207
- }
208
-
209
- this.activeOperations.delete(operationId);
210
-
211
- // Performance marks and measures
212
- if (this.config.enablePerformanceMarks) {
213
- performance.mark(`${operationId}_end`);
214
- performance.measure(operationId, `${operationId}_start`, `${operationId}_end`);
215
- }
216
-
217
- this.log(DebugLevel.DEBUG, 'Performance', `Completed operation: ${entry.operation}`, {
218
- operationId,
219
- duration: entry.duration,
220
- metadata: entry.metadata,
221
- });
222
- }
223
-
224
- /**
225
- * Track render performance
226
- */
227
- trackRender(componentName: string, renderTime: number, propsChanged: boolean = false): void {
228
- if (!this.config.enabled || !this.config.enableRenderTracking) return;
229
-
230
- const existing = this.renderPerformance.get(componentName) || {
231
- componentName,
232
- renderCount: 0,
233
- totalRenderTime: 0,
234
- averageRenderTime: 0,
235
- lastRenderTime: 0,
236
- propsChanges: 0,
237
- };
238
-
239
- existing.renderCount++;
240
- existing.totalRenderTime += renderTime;
241
- existing.averageRenderTime = existing.totalRenderTime / existing.renderCount;
242
- existing.lastRenderTime = renderTime;
243
-
244
- if (propsChanged) {
245
- existing.propsChanges++;
246
- }
247
-
248
- this.renderPerformance.set(componentName, existing);
249
-
250
- this.log(DebugLevel.TRACE, 'Render', `Component rendered: ${componentName}`, {
251
- renderTime,
252
- propsChanged,
253
- averageRenderTime: existing.averageRenderTime,
254
- });
255
- }
256
-
257
- /**
258
- * Take a memory snapshot
259
- */
260
- takeMemorySnapshot(label?: string): MemorySnapshot {
261
- const snapshot: MemorySnapshot = {
262
- timestamp: Date.now(),
263
- heapUsed: 0,
264
- heapTotal: 0,
265
- external: 0,
266
- };
267
-
268
- if ('memory' in performance) {
269
- interface PerformanceMemory {
270
- usedJSHeapSize: number;
271
- totalJSHeapSize: number;
272
- jsHeapSizeLimit: number;
273
- }
274
- const memory = (performance as unknown as { memory: PerformanceMemory }).memory;
275
- snapshot.heapUsed = memory.usedJSHeapSize;
276
- snapshot.heapTotal = memory.totalJSHeapSize;
277
- snapshot.external = memory.usedJSHeapSize;
278
- }
279
-
280
- this.memorySnapshots.push(snapshot);
281
-
282
- // Keep last 100 snapshots
283
- if (this.memorySnapshots.length > 100) {
284
- this.memorySnapshots.shift();
285
- }
286
-
287
- this.log(DebugLevel.DEBUG, 'Memory', `Memory snapshot${label ? ` (${label})` : ''}`, snapshot);
288
-
289
- return snapshot;
290
- }
291
-
292
- /**
293
- * Analyze performance bottlenecks
294
- */
295
- analyzePerformance(): {
296
- slowestOperations: PerformanceTimelineEntry[];
297
- memoryTrends: { increasing: boolean; trend: number };
298
- renderHotspots: RenderPerformanceData[];
299
- recommendations: string[];
300
- } {
301
- const timeline = Array.from(this.performanceTimeline.values())
302
- .filter(entry => entry.duration !== undefined)
303
- .sort((a, b) => (b.duration || 0) - (a.duration || 0));
304
-
305
- const slowestOperations = timeline.slice(0, 10);
306
-
307
- // Memory trend analysis
308
- const recentSnapshots = this.memorySnapshots.slice(-10);
309
- const memoryTrend = recentSnapshots.length > 1
310
- ? (recentSnapshots[recentSnapshots.length - 1].heapUsed - recentSnapshots[0].heapUsed) / recentSnapshots.length
311
- : 0;
312
-
313
- // Render hotspots
314
- const renderHotspots = Array.from(this.renderPerformance.values())
315
- .sort((a, b) => b.averageRenderTime - a.averageRenderTime)
316
- .slice(0, 5);
317
-
318
- // Generate recommendations
319
- const recommendations: string[] = [];
320
-
321
- if (slowestOperations.length > 0 && slowestOperations[0].duration! > 100) {
322
- recommendations.push(`Consider optimizing ${slowestOperations[0].operation} (${slowestOperations[0].duration!.toFixed(2)}ms)`);
323
- }
324
-
325
- if (memoryTrend > 1024 * 1024) { // 1MB increase per snapshot
326
- recommendations.push('Memory usage is increasing rapidly - check for memory leaks');
327
- }
328
-
329
- if (renderHotspots.length > 0 && renderHotspots[0].averageRenderTime > 16.67) { // 60fps threshold
330
- recommendations.push(`${renderHotspots[0].componentName} is rendering slowly - consider memoization`);
331
- }
332
-
333
- return {
334
- slowestOperations,
335
- memoryTrends: {
336
- increasing: memoryTrend > 0,
337
- trend: memoryTrend,
338
- },
339
- renderHotspots,
340
- recommendations,
341
- };
342
- }
343
-
344
- /**
345
- * Generate performance report
346
- */
347
- generateReport(): {
348
- summary: {
349
- totalOperations: number;
350
- averageOperationTime: number;
351
- totalRenders: number;
352
- memorySnapshots: number;
353
- logEntries: number;
354
- };
355
- performance: {
356
- slowestOperations: PerformanceTimelineEntry[];
357
- memoryTrends: { increasing: boolean; trend: number };
358
- renderHotspots: RenderPerformanceData[];
359
- recommendations: string[];
360
- };
361
- logs: DebugLogEntry[];
362
- timeline: PerformanceTimelineEntry[];
363
- } {
364
- const completedOperations = Array.from(this.performanceTimeline.values())
365
- .filter(op => op.duration !== undefined);
366
-
367
- const averageOperationTime = completedOperations.length > 0
368
- ? completedOperations.reduce((sum, op) => sum + (op.duration || 0), 0) / completedOperations.length
369
- : 0;
370
-
371
- const totalRenders = Array.from(this.renderPerformance.values())
372
- .reduce((sum, data) => sum + data.renderCount, 0);
373
-
374
- return {
375
- summary: {
376
- totalOperations: completedOperations.length,
377
- averageOperationTime,
378
- totalRenders,
379
- memorySnapshots: this.memorySnapshots.length,
380
- logEntries: this.logEntries.length,
381
- },
382
- performance: this.analyzePerformance(),
383
- logs: this.logEntries.slice(-50), // Last 50 logs
384
- timeline: Array.from(this.performanceTimeline.values()),
385
- };
386
- }
387
-
388
- /**
389
- * Export debug data
390
- */
391
- exportDebugData(): string {
392
- const report = this.generateReport();
393
- return JSON.stringify(report, null, 2);
394
- }
395
-
396
- /**
397
- * Clear all debug data
398
- */
399
- clear(): void {
400
- this.logEntries = [];
401
- this.performanceTimeline.clear();
402
- this.memorySnapshots = [];
403
- this.renderPerformance.clear();
404
- this.activeOperations.clear();
405
- }
406
-
407
- /**
408
- * Get current memory usage
409
- */
410
- private getCurrentMemoryUsage(): number {
411
- if ('memory' in performance) {
412
- interface PerformanceMemory {
413
- usedJSHeapSize: number;
414
- totalJSHeapSize: number;
415
- jsHeapSizeLimit: number;
416
- }
417
- const memory = (performance as unknown as { memory: PerformanceMemory }).memory;
418
- return memory.usedJSHeapSize / (1024 * 1024); // MB
419
- }
420
- return 0;
421
- }
422
-
423
- /**
424
- * Log to console with appropriate styling
425
- */
426
- private logToConsole(entry: DebugLogEntry): void {
427
- const timestamp = new Date(entry.timestamp).toISOString();
428
- const levelName = DebugLevel[entry.level];
429
- const message = `[${timestamp}] [${levelName}] [${entry.category}] ${entry.message}`;
430
-
431
- switch (entry.level) {
432
- case DebugLevel.ERROR:
433
- this.logger.error(message, entry.data);
434
- break;
435
- case DebugLevel.WARN:
436
- this.logger.warn(message, entry.data);
437
- break;
438
- case DebugLevel.INFO:
439
- this.logger.info(message, entry.data);
440
- break;
441
- case DebugLevel.DEBUG:
442
- case DebugLevel.TRACE:
443
- this.logger.debug(message, entry.data);
444
- break;
445
- }
446
- }
447
-
448
- /**
449
- * Log to local storage
450
- */
451
- private logToStorage(entry: DebugLogEntry): void {
452
- if (typeof window === 'undefined') return;
453
-
454
- try {
455
- const stored = localStorage.getItem('datatable-debug-logs');
456
- const logs = stored ? JSON.parse(stored) : [];
457
- logs.push(entry);
458
-
459
- // Keep last 500 entries
460
- if (logs.length > 500) {
461
- logs.splice(0, logs.length - 500);
462
- }
463
-
464
- localStorage.setItem('datatable-debug-logs', JSON.stringify(logs));
465
- } catch (error) {
466
- this.logger.warn('Failed to store debug log:', error);
467
- }
468
- }
469
- }
470
-
471
- /**
472
- * Global debugger instance (internal use only)
473
- */
474
- const dataTableDebugger = new DataTableDebugger();
475
-
476
- /**
477
- * Development tools integration
478
- */
479
- export function setupDevTools(): void {
480
- if (typeof window === 'undefined' || import.meta.env.MODE !== 'development') {
481
- return;
482
- }
483
-
484
- // Expose debugger to global scope for browser dev tools
485
- interface WindowWithDataTableDebugger extends Window {
486
- __DATATABLE_DEBUGGER__: typeof dataTableDebugger;
487
- dataTableDebug: {
488
- getReport: () => ReturnType<typeof dataTableDebugger.generateReport>;
489
- exportData: () => ReturnType<typeof dataTableDebugger.exportDebugData>;
490
- clearLogs: () => void;
491
- takeSnapshot: (label?: string) => ReturnType<typeof dataTableDebugger.takeMemorySnapshot>;
492
- analyze: () => ReturnType<typeof dataTableDebugger.analyzePerformance>;
493
- };
494
- }
495
-
496
- const windowWithDebugger = window as unknown as WindowWithDataTableDebugger;
497
- windowWithDebugger.__DATATABLE_DEBUGGER__ = dataTableDebugger;
498
-
499
- // Add console commands
500
- windowWithDebugger.dataTableDebug = {
501
- getReport: () => dataTableDebugger.generateReport(),
502
- exportData: () => dataTableDebugger.exportDebugData(),
503
- clearLogs: () => dataTableDebugger.clear(),
504
- takeSnapshot: (label?: string) => dataTableDebugger.takeMemorySnapshot(label),
505
- analyze: () => dataTableDebugger.analyzePerformance(),
506
- };
507
-
508
- createLogger('DataTableDebugTools').info('Debug Tools loaded. Use window.dataTableDebug for debugging.');
509
- }
510
-
511
- /**
512
- * Initialize debugging tools
513
- */
514
- setupDevTools();
@@ -1,22 +0,0 @@
1
- /**
2
- * Main entry point for pace-core ESLint rules
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules
5
- *
6
- * This module exports all pace-core compliance ESLint rules organized by category.
7
- */
8
-
9
- const complianceRules = require('./rules/compliance.cjs');
10
- const componentRules = require('./rules/components.cjs');
11
- const rbacRules = require('./rules/rbac.cjs');
12
- const importRules = require('./rules/imports.cjs');
13
-
14
- module.exports = {
15
- rules: {
16
- ...complianceRules.rules,
17
- ...componentRules.rules,
18
- ...rbacRules.rules,
19
- ...importRules.rules,
20
- }
21
- };
22
-
@@ -1,113 +0,0 @@
1
- /**
2
- * Component usage rules
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules/rules/components
5
- */
6
-
7
- const { isPaceCoreSourceFile } = require('../utils/helpers.cjs');
8
-
9
- module.exports = {
10
- rules: {
11
- /**
12
- * Prefer pace-core Form component over plain form tags and direct react-hook-form usage
13
- */
14
- 'prefer-pace-core-form': {
15
- meta: {
16
- type: 'problem',
17
- docs: {
18
- description: 'Disallow plain <form> tags and direct react-hook-form imports. Use pace-core Form component instead.',
19
- category: 'Best Practices',
20
- recommended: true
21
- },
22
- messages: {
23
- plainFormTag: "Plain <form> tag detected. Use pace-core Form component instead.",
24
- reactHookFormImport: "Direct import from 'react-hook-form' detected: {{imports}}. Use pace-core Form component instead. useFormContext is allowed when Form is imported from pace-core."
25
- },
26
- hasSuggestions: true
27
- },
28
- create(context) {
29
- const filename = context.getFilename();
30
-
31
- // Exclude pace-core source files - these rules are for consuming apps
32
- if (isPaceCoreSourceFile(filename)) {
33
- return {};
34
- }
35
-
36
- let hasPaceCoreForm = false;
37
- const problematicImports = ['useForm', 'FormProvider', 'Controller', 'useWatch', 'useFieldArray', 'useController'];
38
-
39
- return {
40
- ImportDeclaration(node) {
41
- const importSource = node.source.value;
42
-
43
- // Check if Form is imported from pace-core
44
- if (importSource === '@jmruthers/pace-core' ||
45
- importSource === '@jmruthers/pace-core/components') {
46
- const hasForm = node.specifiers.some(spec => {
47
- if (spec.type === 'ImportSpecifier') {
48
- return spec.imported.name === 'Form';
49
- }
50
- return false;
51
- });
52
- if (hasForm) {
53
- hasPaceCoreForm = true;
54
- }
55
- }
56
-
57
- // Check for react-hook-form imports
58
- if (importSource === 'react-hook-form') {
59
- const importedItems = node.specifiers
60
- .filter(spec => spec.type === 'ImportSpecifier')
61
- .map(spec => spec.imported.name);
62
-
63
- const foundProblematic = importedItems.filter(item => problematicImports.includes(item));
64
-
65
- // Allow useFormContext when Form is imported from pace-core
66
- const isAcceptable = hasPaceCoreForm &&
67
- foundProblematic.length === 1 &&
68
- foundProblematic[0] === 'useFormContext';
69
-
70
- if (foundProblematic.length > 0 && !isAcceptable) {
71
- context.report({
72
- node: node.source,
73
- messageId: 'reactHookFormImport',
74
- data: {
75
- imports: foundProblematic.join(', ')
76
- },
77
- suggest: [{
78
- desc: 'Use pace-core Form component instead',
79
- fix(fixer) {
80
- return fixer.remove(node);
81
- }
82
- }]
83
- });
84
- }
85
- }
86
- },
87
-
88
- JSXOpeningElement(node) {
89
- // Check for plain <form> tags (lowercase, not Form component)
90
- if (node.name.type === 'JSXIdentifier') {
91
- const elementName = node.name.name;
92
- // Check if it's lowercase 'form' (not 'Form' component)
93
- if (elementName === 'form') {
94
- context.report({
95
- node,
96
- messageId: 'plainFormTag',
97
- suggest: [{
98
- desc: 'Replace with pace-core Form component',
99
- fix(fixer) {
100
- // This is complex to auto-fix, so we'll just report
101
- return null;
102
- }
103
- }]
104
- });
105
- }
106
- }
107
- }
108
- };
109
- }
110
- }
111
- }
112
- };
113
-