@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,19 +1,18 @@
1
- #!/usr/bin/env node
2
-
3
1
  /**
4
- * Dependency Audit Script
2
+ * Dependencies Audit (Pre-Standard)
3
+ * @package @jmruthers/pace-core
4
+ * @module Audit/Dependencies
5
+ *
6
+ * Audits consuming apps for dependency compliance with pace-core.
7
+ * This runs before standard audits as it validates the foundation.
5
8
  *
6
- * Audits consuming apps against pace-core dependency standards.
7
9
  * Checks for:
8
10
  * - Included dependencies that should NOT be installed
9
11
  * - Missing required peer dependencies
10
12
  * - Incorrect version ranges
11
- * - Dependencies in wrong location (devDependencies vs dependencies)
12
- *
13
- * Usage:
14
- * node scripts/audit/audit-dependencies.cjs [path-to-consuming-app]
13
+ * - Dependencies in the wrong location
15
14
  *
16
- * If no path provided, assumes current directory is consuming app.
15
+ * Reference: packages/core/docs/standards/1-pace-core-compliance-standards.md
17
16
  */
18
17
 
19
18
  const fs = require('fs');
@@ -31,12 +30,12 @@ const colors = {
31
30
  };
32
31
 
33
32
  // Get pace-core package.json
34
- // When run from consuming app: __dirname is node_modules/@jmruthers/pace-core/scripts/audit
35
- // When run from pace-core repo: __dirname is packages/core/scripts/audit
33
+ // When run from consuming app: __dirname is node_modules/@jmruthers/pace-core/audit-tool
34
+ // When run from pace-core repo: __dirname is packages/core/audit-tool
36
35
  function findPaceCorePackageJson(consumingAppPath) {
37
36
  // Try relative to script location first (when in pace-core repo or installed package)
38
- // Now we're in audit/ subdirectory, so need to go up two levels
39
- let paceCorePath = path.resolve(__dirname, '../../package.json');
37
+ // Now we're in audit-tool/ directory, so need to go up one level
38
+ let paceCorePath = path.resolve(__dirname, '../package.json');
40
39
  if (fs.existsSync(paceCorePath)) {
41
40
  return paceCorePath;
42
41
  }
@@ -81,6 +80,24 @@ function matchesVersionRange(version, range) {
81
80
  return version.startsWith(range.replace(/[\^~]/, ''));
82
81
  }
83
82
 
83
+ // Compare two version strings (e.g., "4.1.8" vs "4.1.16")
84
+ // Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
85
+ function compareVersions(v1, v2) {
86
+ const parts1 = v1.split('.').map(Number);
87
+ const parts2 = v2.split('.').map(Number);
88
+ const maxLength = Math.max(parts1.length, parts2.length);
89
+
90
+ for (let i = 0; i < maxLength; i++) {
91
+ const part1 = parts1[i] || 0;
92
+ const part2 = parts2[i] || 0;
93
+
94
+ if (part1 < part2) return -1;
95
+ if (part1 > part2) return 1;
96
+ }
97
+
98
+ return 0;
99
+ }
100
+
84
101
  // Check version compatibility
85
102
  function checkVersion(installed, required) {
86
103
  if (!required) return { valid: true };
@@ -89,18 +106,46 @@ function checkVersion(installed, required) {
89
106
  const installedVersion = installed.replace(/[\^~]/, '');
90
107
  const requiredVersion = required.replace(/[\^~]/, '');
91
108
 
92
- // Check major version
93
- const installedMajor = parseInt(installedVersion.split('.')[0]);
94
- const requiredMajor = parseInt(requiredVersion.split('.')[0]);
109
+ // Parse version parts
110
+ const installedParts = installedVersion.split('.').map(Number);
111
+ const requiredParts = requiredVersion.split('.').map(Number);
112
+
113
+ const installedMajor = installedParts[0] || 0;
114
+ const requiredMajor = requiredParts[0] || 0;
95
115
 
96
116
  if (required.startsWith('^')) {
117
+ // Caret range: ^4.1.16 means >= 4.1.16 and < 5.0.0
118
+ // Check if installed version is >= required version
119
+ const versionComparison = compareVersions(installedVersion, requiredVersion);
120
+
121
+ // Must be same major version and >= required version
122
+ const valid = installedMajor === requiredMajor && versionComparison >= 0;
123
+
124
+ return {
125
+ valid,
126
+ installed,
127
+ required,
128
+ };
129
+ }
130
+
131
+ if (required.startsWith('~')) {
132
+ // Tilde range: ~4.1.16 means >= 4.1.16 and < 4.2.0
133
+ const versionComparison = compareVersions(installedVersion, requiredVersion);
134
+ const installedMinor = installedParts[1] || 0;
135
+ const requiredMinor = requiredParts[1] || 0;
136
+
137
+ const valid = installedMajor === requiredMajor &&
138
+ installedMinor === requiredMinor &&
139
+ versionComparison >= 0;
140
+
97
141
  return {
98
- valid: installedMajor >= requiredMajor,
142
+ valid,
99
143
  installed,
100
144
  required,
101
145
  };
102
146
  }
103
147
 
148
+ // Exact match or no prefix - check major version
104
149
  return {
105
150
  valid: installedMajor === requiredMajor,
106
151
  installed,
@@ -115,7 +160,7 @@ function runDependencyAudit(consumingAppPath = process.cwd()) {
115
160
  if (!fs.existsSync(packageJsonPath)) {
116
161
  return {
117
162
  error: `package.json not found at ${packageJsonPath}`,
118
- issues: { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [] }
163
+ issues: { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [], missingDevDeps: [], devVersionIssues: [] }
119
164
  };
120
165
  }
121
166
 
@@ -124,22 +169,41 @@ function runDependencyAudit(consumingAppPath = process.cwd()) {
124
169
  if (!paceCorePath) {
125
170
  return {
126
171
  error: 'Could not find pace-core package.json. Make sure @jmruthers/pace-core is installed in your project.',
127
- issues: { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [] }
172
+ issues: { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [], missingDevDeps: [], devVersionIssues: [] }
128
173
  };
129
174
  }
130
175
 
131
176
  const paceCorePkg = JSON.parse(fs.readFileSync(paceCorePath, 'utf8'));
132
177
  const INCLUDED_DEPS = Object.keys(paceCorePkg.dependencies || {});
133
178
  const PEER_DEPS = paceCorePkg.peerDependencies || {};
134
- const REQUIRED_PEERS = ['react', 'react-dom', 'react-router-dom', 'tailwindcss'];
135
- const OPTIONAL_PEERS = Object.keys(PEER_DEPS).filter(dep => !REQUIRED_PEERS.includes(dep));
179
+ const PEER_META = paceCorePkg.peerDependenciesMeta || {};
180
+
181
+ // Required peers are those NOT marked as optional in peerDependenciesMeta
182
+ const REQUIRED_PEERS = Object.keys(PEER_DEPS).filter(
183
+ dep => !PEER_META[dep]?.optional
184
+ );
185
+
186
+ // Optional peers are those marked as optional in peerDependenciesMeta
187
+ const OPTIONAL_PEERS = Object.keys(PEER_DEPS).filter(
188
+ dep => PEER_META[dep]?.optional
189
+ );
190
+
191
+ // Validation warnings: check if any peer dependency is missing from peerDependenciesMeta
192
+ const missingMeta = Object.keys(PEER_DEPS).filter(
193
+ dep => !PEER_META[dep]
194
+ );
195
+
196
+ if (missingMeta.length > 0) {
197
+ console.warn(`${colors.yellow}Warning: The following peer dependencies are missing from peerDependenciesMeta: ${missingMeta.join(', ')}${colors.reset}`);
198
+ console.warn(`${colors.yellow}They will be treated as required. Add them to peerDependenciesMeta to mark them as optional.${colors.reset}`);
199
+ }
136
200
 
137
201
  // Verify pace-core is installed
138
202
  const paceCoreInNodeModules = path.join(consumingAppPath, 'node_modules', '@jmruthers', 'pace-core', 'package.json');
139
203
  if (!fs.existsSync(paceCoreInNodeModules)) {
140
204
  return {
141
205
  error: '@jmruthers/pace-core not found in node_modules. Please run: npm install @jmruthers/pace-core',
142
- issues: { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [] }
206
+ issues: { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [], missingDevDeps: [], devVersionIssues: [] }
143
207
  };
144
208
  }
145
209
 
@@ -155,6 +219,8 @@ function runDependencyAudit(consumingAppPath = process.cwd()) {
155
219
  missingOptional: [],
156
220
  versionIssues: [],
157
221
  wrongLocation: [],
222
+ missingDevDeps: [],
223
+ devVersionIssues: [],
158
224
  };
159
225
 
160
226
  // Check for included dependencies
@@ -217,6 +283,107 @@ function runDependencyAudit(consumingAppPath = process.cwd()) {
217
283
  });
218
284
  }
219
285
 
286
+ // Check required dev dependencies
287
+ // Get pace-core's dev dependencies to use as reference versions
288
+ const paceCoreDevDeps = paceCorePkg.devDependencies || {};
289
+ const devDeps = consumingPkg.devDependencies || {};
290
+
291
+ // Build list of required dev dependencies dynamically from pace-core's devDependencies
292
+ // Exclude packages that consuming apps don't need:
293
+ // 1. pace-core-specific build tools (tsup, typedoc, etc.)
294
+ // 2. Testing libraries (consuming apps may use different testing setups)
295
+ // 3. Type definitions (@types/* - consuming apps manage their own)
296
+ // 4. Packages already checked as peer dependencies (except tailwindcss which we check in both)
297
+ // 5. Packages already included in pace-core's dependencies
298
+
299
+ const requiredDevDeps = {};
300
+
301
+ Object.entries(paceCoreDevDeps).forEach(([dep, version]) => {
302
+ // Skip pace-core-specific build tools
303
+ if (dep === 'tsup' ||
304
+ dep === 'typedoc' ||
305
+ dep.startsWith('typedoc-plugin-') ||
306
+ dep === 'esbuild' ||
307
+ dep === '@vitest/coverage-v8') {
308
+ return;
309
+ }
310
+
311
+ // Skip testing libraries (consuming apps may use different testing)
312
+ if (dep.includes('testing-library') ||
313
+ dep === 'jsdom' ||
314
+ dep === 'vitest') {
315
+ return;
316
+ }
317
+
318
+ // Skip type definitions (consuming apps manage their own @types/*)
319
+ if (dep.startsWith('@types/')) {
320
+ return;
321
+ }
322
+
323
+ // Skip if it's already a peer dependency (checked separately)
324
+ // Exception: tailwindcss - we check both peer and dev dependency versions
325
+ if (PEER_DEPS[dep] && dep !== 'tailwindcss') {
326
+ return;
327
+ }
328
+
329
+ // Skip if it's already in pace-core's dependencies (included, not needed by consuming apps)
330
+ if (INCLUDED_DEPS.includes(dep)) {
331
+ return;
332
+ }
333
+
334
+ // Skip if it's in pace-core's dependencies (shouldn't be in devDependencies)
335
+ if (paceCorePkg.dependencies?.[dep]) {
336
+ return;
337
+ }
338
+
339
+ // Add to required dev dependencies - versions come directly from pace-core's package.json
340
+ requiredDevDeps[dep] = version;
341
+ });
342
+
343
+ // Override tailwindcss version with peer dependency version if available
344
+ // This ensures we use the peer dependency requirement, not the dev dependency version
345
+ if (PEER_DEPS.tailwindcss) {
346
+ requiredDevDeps.tailwindcss = PEER_DEPS.tailwindcss;
347
+ }
348
+
349
+ // Check for missing required dev dependencies
350
+ Object.entries(requiredDevDeps).forEach(([dep, requiredVersion]) => {
351
+ if (!requiredVersion) return; // Skip if pace-core doesn't specify a version
352
+
353
+ if (!devDeps[dep] && !consumingPkg.dependencies?.[dep]) {
354
+ issues.missingDevDeps.push({
355
+ package: dep,
356
+ required: requiredVersion,
357
+ });
358
+ } else {
359
+ // Check version if installed
360
+ const installedVersion = devDeps[dep] || consumingPkg.dependencies?.[dep];
361
+ if (installedVersion) {
362
+ const versionCheck = checkVersion(installedVersion, requiredVersion);
363
+ if (!versionCheck.valid) {
364
+ issues.devVersionIssues.push({
365
+ package: dep,
366
+ installed: versionCheck.installed,
367
+ required: versionCheck.required,
368
+ location: devDeps[dep] ? 'devDependencies' : 'dependencies',
369
+ });
370
+ }
371
+ }
372
+ }
373
+ });
374
+
375
+ // Check for dev dependencies in wrong location (should be in devDependencies, not dependencies)
376
+ // This is dynamic - check all required dev dependencies
377
+ Object.keys(requiredDevDeps).forEach(dep => {
378
+ if (consumingPkg.dependencies?.[dep] && !devDeps[dep]) {
379
+ issues.wrongLocation.push({
380
+ package: dep,
381
+ current: 'dependencies',
382
+ shouldBe: 'devDependencies',
383
+ });
384
+ }
385
+ });
386
+
220
387
  // Find pace-core version - check dependencies, devDependencies, or installed package
221
388
  let paceCoreVersion = consumingPkg.dependencies?.['@jmruthers/pace-core'] ||
222
389
  consumingPkg.devDependencies?.['@jmruthers/pace-core'];
@@ -316,6 +483,28 @@ function auditDependencies(consumingAppPath = process.cwd()) {
316
483
  console.log();
317
484
  }
318
485
 
486
+ // Missing dev dependencies (errors)
487
+ if (issues.missingDevDeps.length > 0) {
488
+ hasErrors = true;
489
+ console.log(`${colors.red}❌ MISSING REQUIRED DEV DEPENDENCIES:${colors.reset}`);
490
+ issues.missingDevDeps.forEach(issue => {
491
+ console.log(` - ${colors.red}${issue.package}${colors.reset} (required: ${issue.required})`);
492
+ });
493
+ console.log();
494
+ }
495
+
496
+ // Dev version issues (errors)
497
+ if (issues.devVersionIssues.length > 0) {
498
+ hasErrors = true;
499
+ console.log(`${colors.yellow}⚠️ DEV DEPENDENCY VERSION ISSUES:${colors.reset}`);
500
+ issues.devVersionIssues.forEach(issue => {
501
+ console.log(` - ${colors.yellow}${issue.package}${colors.reset} (in ${issue.location})`);
502
+ console.log(` Installed: ${issue.installed}`);
503
+ console.log(` Required: ${issue.required}`);
504
+ });
505
+ console.log();
506
+ }
507
+
319
508
  // Success message
320
509
  if (!hasErrors && issues.missingOptional.length === 0 && issues.wrongLocation.length === 0) {
321
510
  console.log(`${colors.green}✅ All dependencies are correctly configured!${colors.reset}\n`);
@@ -340,6 +529,14 @@ function auditDependencies(consumingAppPath = process.cwd()) {
340
529
  console.log(`npm install ${depsToInstall}\n`);
341
530
  }
342
531
 
532
+ if (issues.missingDevDeps.length > 0) {
533
+ const devDepsToInstall = issues.missingDevDeps
534
+ .map(i => `${i.package}@${i.required}`)
535
+ .join(' ');
536
+ console.log(`${colors.cyan}# Install missing required dev dependencies${colors.reset}`);
537
+ console.log(`npm install -D ${devDepsToInstall}\n`);
538
+ }
539
+
343
540
  if (issues.versionIssues.length > 0) {
344
541
  const depsToFix = issues.versionIssues
345
542
  .map(i => `${i.package}@${i.required}`)
@@ -348,6 +545,14 @@ function auditDependencies(consumingAppPath = process.cwd()) {
348
545
  console.log(`npm install ${depsToFix}\n`);
349
546
  }
350
547
 
548
+ if (issues.devVersionIssues.length > 0) {
549
+ const devDepsToFix = issues.devVersionIssues
550
+ .map(i => `${i.package}@${i.required}`)
551
+ .join(' ');
552
+ console.log(`${colors.cyan}# Fix dev dependency version ranges${colors.reset}`);
553
+ console.log(`npm install -D ${devDepsToFix}\n`);
554
+ }
555
+
351
556
  if (issues.wrongLocation.length > 0) {
352
557
  issues.wrongLocation.forEach(issue => {
353
558
  console.log(`${colors.cyan}# Move ${issue.package} to devDependencies${colors.reset}`);