@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.
Files changed (246) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +255 -0
  4. package/audit-tool/audits/03-architecture.cjs +196 -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 +544 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +301 -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 +291 -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 +241 -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-7PMH7XN7.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-DlsCaR5v.d.ts} +26 -16
  28. package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
  29. package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
  30. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  31. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  32. package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
  33. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  34. package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
  35. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  36. package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
  37. package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
  38. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  39. package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
  40. package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
  41. package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
  42. package/dist/components.d.ts +5 -4
  43. package/dist/components.js +27 -32
  44. package/dist/eslint-rules/index.cjs +22 -9
  45. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  46. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  47. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  48. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
  49. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  50. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  51. package/dist/hooks.d.ts +5 -5
  52. package/dist/hooks.js +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +18 -17
  55. package/dist/rbac/index.js +6 -6
  56. package/dist/theming/runtime.d.ts +14 -1
  57. package/dist/theming/runtime.js +1 -1
  58. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  59. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  60. package/dist/utils.d.ts +2 -2
  61. package/dist/utils.js +8 -8
  62. package/docs/README.md +1 -1
  63. package/docs/api/modules.md +47 -31
  64. package/docs/api-reference/components.md +18 -20
  65. package/docs/api-reference/hooks.md +80 -80
  66. package/docs/api-reference/types.md +1 -1
  67. package/docs/api-reference/utilities.md +1 -1
  68. package/docs/architecture/README.md +1 -1
  69. package/docs/core-concepts/events.md +3 -3
  70. package/docs/core-concepts/organisations.md +6 -6
  71. package/docs/core-concepts/permissions.md +6 -6
  72. package/docs/documentation-index.md +12 -18
  73. package/docs/getting-started/documentation-index.md +1 -1
  74. package/docs/getting-started/examples/README.md +4 -4
  75. package/docs/getting-started/examples/full-featured-app.md +1 -1
  76. package/docs/getting-started/faq.md +2 -2
  77. package/docs/getting-started/quick-reference.md +4 -4
  78. package/docs/implementation-guides/authentication.md +15 -15
  79. package/docs/implementation-guides/component-styling.md +1 -1
  80. package/docs/implementation-guides/data-tables.md +126 -33
  81. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  82. package/docs/implementation-guides/dynamic-colors.md +3 -3
  83. package/docs/implementation-guides/file-upload-storage.md +2 -2
  84. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  85. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  86. package/docs/implementation-guides/large-datasets.md +3 -2
  87. package/docs/implementation-guides/organisation-security.md +2 -2
  88. package/docs/implementation-guides/performance.md +2 -2
  89. package/docs/implementation-guides/permission-enforcement.md +1 -1
  90. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  91. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  92. package/docs/rbac/README.md +5 -5
  93. package/docs/rbac/advanced-patterns.md +6 -6
  94. package/docs/rbac/api-reference.md +20 -20
  95. package/docs/rbac/event-based-apps.md +3 -3
  96. package/docs/rbac/examples.md +41 -41
  97. package/docs/rbac/getting-started.md +37 -37
  98. package/docs/rbac/performance.md +1 -1
  99. package/docs/rbac/quick-start.md +52 -52
  100. package/docs/rbac/secure-client-protection.md +1 -1
  101. package/docs/rbac/troubleshooting.md +1 -1
  102. package/docs/security/README.md +5 -5
  103. package/docs/standards/0-standards-overview.md +220 -0
  104. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
  105. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  106. package/docs/standards/3-architecture-standards.md +606 -0
  107. package/docs/standards/4-code-quality-standards.md +728 -0
  108. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  109. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  110. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  111. package/docs/standards/8-testing-documentation-standards.md +401 -0
  112. package/docs/standards/9-operations-standards.md +1102 -0
  113. package/docs/standards/README.md +203 -104
  114. package/docs/troubleshooting/README.md +4 -4
  115. package/docs/troubleshooting/common-issues.md +2 -2
  116. package/docs/troubleshooting/debugging.md +9 -9
  117. package/docs/troubleshooting/migration.md +4 -4
  118. package/eslint-config-pace-core.cjs +21 -10
  119. package/package.json +6 -5
  120. package/scripts/install-cursor-rules.cjs +11 -243
  121. package/scripts/install-eslint-config.cjs +284 -0
  122. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  123. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  124. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
  125. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  126. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  127. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  128. package/src/__tests__/templates/component.test.template.tsx +18 -15
  129. package/src/components/Calendar/Calendar.tsx +201 -47
  130. package/src/components/ContextSelector/ContextSelector.tsx +137 -153
  131. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  132. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  133. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  134. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  135. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  136. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  137. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  138. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  139. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  140. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  141. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  142. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  143. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  144. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  145. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  146. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  147. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  148. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  149. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  150. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  151. package/src/components/DataTable/components/index.ts +2 -1
  152. package/src/components/DataTable/types.ts +0 -18
  153. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  154. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  155. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  156. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  157. package/src/components/Dialog/Dialog.test.tsx +1 -0
  158. package/src/components/Dialog/Dialog.tsx +25 -8
  159. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  160. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  161. package/src/components/FileUpload/FileUpload.tsx +112 -130
  162. package/src/components/Progress/Progress.tsx +2 -4
  163. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  164. package/src/components/Select/Select.tsx +86 -77
  165. package/src/components/Select/types.ts +3 -0
  166. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  167. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  168. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  169. package/src/hooks/public/usePublicEvent.ts +5 -5
  170. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  171. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  172. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  173. package/src/hooks/useAppConfig.ts +2 -2
  174. package/src/hooks/useEventTheme.test.ts +7 -7
  175. package/src/hooks/useEventTheme.ts +1 -4
  176. package/src/hooks/useFileDisplay.ts +2 -2
  177. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  178. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  179. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  180. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  181. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  182. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  183. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  184. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  185. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  186. package/src/styles/core.css +7 -0
  187. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  188. package/src/theming/parseEventColours.ts +22 -10
  189. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  190. package/src/utils/storage/README.md +1 -1
  191. package/cursor-rules/01-standards-compliance.mdc +0 -285
  192. package/cursor-rules/04-testing-standards.mdc +0 -270
  193. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  194. package/cursor-rules/06-code-quality.mdc +0 -311
  195. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  196. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  197. package/cursor-rules/11-performance-optimization.mdc +0 -169
  198. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  199. package/dist/DataTable-LRJL4IRV.js +0 -15
  200. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  201. package/dist/eslint-rules/rules/components.cjs +0 -113
  202. package/dist/eslint-rules/rules/imports.cjs +0 -102
  203. package/docs/best-practices/README.md +0 -472
  204. package/docs/best-practices/accessibility.md +0 -604
  205. package/docs/best-practices/common-patterns.md +0 -516
  206. package/docs/best-practices/deployment.md +0 -1103
  207. package/docs/best-practices/performance.md +0 -1328
  208. package/docs/best-practices/security.md +0 -940
  209. package/docs/best-practices/testing.md +0 -1034
  210. package/docs/rbac/compliance/compliance-guide.md +0 -544
  211. package/docs/standards/01-standards-compliance.md +0 -188
  212. package/docs/standards/03-solid-principles.md +0 -39
  213. package/docs/standards/04-testing-standards.md +0 -36
  214. package/docs/standards/05-bug-reports-and-features.md +0 -27
  215. package/docs/standards/06-code-quality.md +0 -34
  216. package/docs/standards/07-tech-stack-compliance.md +0 -30
  217. package/docs/standards/10-error-handling-patterns.md +0 -401
  218. package/docs/standards/11-performance-optimization.md +0 -348
  219. package/docs/standards/12-ci-cd-integration.md +0 -370
  220. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  221. package/scripts/audit/audit-compliance.cjs +0 -1295
  222. package/scripts/audit/audit-components.cjs +0 -260
  223. package/scripts/audit/audit-rbac.cjs +0 -954
  224. package/scripts/audit/audit-standards.cjs +0 -1268
  225. package/scripts/audit/index.cjs +0 -1927
  226. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  227. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  228. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  229. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  230. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  231. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  232. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  233. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  234. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  235. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  236. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  237. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  238. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  239. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  240. package/src/components/DataTable/utils/debugTools.ts +0 -514
  241. package/src/eslint-rules/index.cjs +0 -22
  242. package/src/eslint-rules/rules/components.cjs +0 -113
  243. package/src/eslint-rules/rules/imports.cjs +0 -102
  244. package/src/eslint-rules/rules/rbac.cjs +0 -790
  245. package/src/eslint-rules/utils/helpers.cjs +0 -42
  246. 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
-