@jmruthers/pace-core 0.5.193 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/README.md +7 -1
- package/cursor-rules/00-pace-core-compliance.mdc +299 -0
- package/cursor-rules/01-standards-compliance.mdc +244 -0
- package/cursor-rules/02-project-structure.mdc +200 -0
- package/cursor-rules/03-solid-principles.mdc +222 -0
- package/cursor-rules/04-testing-standards.mdc +268 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
- package/cursor-rules/06-code-quality.mdc +309 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +119 -0
- package/cursor-rules/README.md +192 -0
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
- package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
- package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
- package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
- package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
- package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
- package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
- package/dist/chunk-24UVZUZG.js.map +1 -0
- package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
- package/dist/chunk-2UOI2FG5.js.map +1 -0
- package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
- package/dist/chunk-3XC4CPTD.js.map +1 -0
- package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
- package/dist/chunk-6J4GEEJR.js.map +1 -0
- package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
- package/dist/chunk-EHMR7VYL.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
- package/dist/chunk-FFQEQTNW.js.map +1 -0
- package/dist/chunk-FMUCXFII.js +76 -0
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
- package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
- package/dist/chunk-MMZ7JXPU.js.map +1 -0
- package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
- package/dist/chunk-NECFR5MM.js.map +1 -0
- package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
- package/dist/chunk-SFZUDBL5.js.map +1 -0
- package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
- package/dist/chunk-XWQCNGTQ.js.map +1 -0
- package/dist/components.d.ts +6 -6
- package/dist/components.js +15 -12
- package/dist/components.js.map +1 -1
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +59 -126
- package/dist/hooks.js +19 -28
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +63 -16
- package/dist/index.js +23 -24
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +146 -115
- package/dist/rbac/index.js +8 -11
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
- package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
- package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
- package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +15 -15
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +7 -1
- package/docs/api/classes/ColumnFactory.md +8 -8
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +18 -15
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +9 -2
- package/docs/api/interfaces/ButtonProps.md +7 -4
- package/docs/api/interfaces/CalendarProps.md +8 -5
- package/docs/api/interfaces/CardProps.md +8 -5
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +24 -21
- package/docs/api/interfaces/DataTableColumn.md +31 -31
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +26 -23
- package/docs/api/interfaces/FooterProps.md +10 -8
- package/docs/api/interfaces/FormFieldProps.md +10 -10
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +7 -4
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +14 -11
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +11 -11
- package/docs/api/interfaces/NavigationMenuProps.md +15 -15
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +30 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
- package/docs/api/interfaces/SetupIssue.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +3 -3
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +4 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +14 -11
- package/docs/api/interfaces/UserMenuProps.md +8 -6
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +575 -634
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +263 -0
- package/docs/getting-started/installation-guide.md +6 -1
- package/docs/getting-started/quick-start.md +6 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +6 -28
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/rbac/event-based-apps.md +1 -1
- package/docs/rbac/getting-started.md +1 -1
- package/docs/rbac/quick-start.md +1 -1
- package/docs/standards/README.md +40 -0
- package/docs/troubleshooting/migration.md +4 -4
- package/examples/PublicPages/PublicEventPage.tsx +1 -1
- package/package.json +12 -6
- package/scripts/audit/core/checks/accessibility.cjs +197 -0
- package/scripts/audit/core/checks/api-usage.cjs +191 -0
- package/scripts/audit/core/checks/bundle.cjs +142 -0
- package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
- package/scripts/audit/core/checks/config.cjs +54 -0
- package/scripts/audit/core/checks/coverage.cjs +84 -0
- package/scripts/audit/core/checks/dependencies.cjs +454 -0
- package/scripts/audit/core/checks/documentation.cjs +203 -0
- package/scripts/audit/core/checks/environment.cjs +128 -0
- package/scripts/audit/core/checks/error-handling.cjs +299 -0
- package/scripts/audit/core/checks/forms.cjs +172 -0
- package/scripts/audit/core/checks/heuristics.cjs +68 -0
- package/scripts/audit/core/checks/hooks.cjs +334 -0
- package/scripts/audit/core/checks/imports.cjs +244 -0
- package/scripts/audit/core/checks/performance.cjs +325 -0
- package/scripts/audit/core/checks/routes.cjs +117 -0
- package/scripts/audit/core/checks/state.cjs +130 -0
- package/scripts/audit/core/checks/structure.cjs +65 -0
- package/scripts/audit/core/checks/style.cjs +584 -0
- package/scripts/audit/core/checks/testing.cjs +122 -0
- package/scripts/audit/core/checks/typescript.cjs +61 -0
- package/scripts/audit/core/scanner.cjs +199 -0
- package/scripts/audit/core/utils.cjs +137 -0
- package/scripts/audit/index.cjs +223 -0
- package/scripts/audit/reporters/console.cjs +151 -0
- package/scripts/audit/reporters/json.cjs +54 -0
- package/scripts/audit/reporters/markdown.cjs +124 -0
- package/scripts/audit-consuming-app.cjs +86 -0
- package/scripts/build-docs/build-decision.js +240 -0
- package/scripts/build-docs/cache-utils.js +105 -0
- package/scripts/build-docs/content-normalization.js +150 -0
- package/scripts/build-docs/file-utils.js +105 -0
- package/scripts/build-docs/git-utils.js +86 -0
- package/scripts/build-docs/hash-utils.js +116 -0
- package/scripts/build-docs/typedoc-runner.js +220 -0
- package/scripts/build-docs-incremental.js +77 -913
- package/scripts/install-cursor-rules.cjs +236 -0
- package/scripts/utils/command-runner.js +16 -11
- package/scripts/validate-formats.js +61 -56
- package/scripts/validate-master.js +74 -69
- package/scripts/validate-pre-publish.js +70 -65
- package/src/__tests__/helpers/test-providers.tsx +1 -1
- package/src/__tests__/helpers/test-utils.tsx +1 -1
- package/src/__tests__/hooks/usePermissions.test.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +12 -18
- package/src/components/Alert/Alert.tsx +5 -7
- package/src/components/Avatar/Avatar.test.tsx +4 -4
- package/src/components/Badge/Badge.tsx +16 -4
- package/src/components/Button/Button.tsx +27 -4
- package/src/components/Calendar/Calendar.tsx +9 -3
- package/src/components/Card/Card.tsx +4 -0
- package/src/components/Checkbox/Checkbox.test.tsx +12 -12
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/DataTable.test.tsx +57 -93
- package/src/components/DataTable/DataTable.tsx +40 -6
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
- package/src/components/DataTable/components/DataTableBody.tsx +8 -0
- package/src/components/DataTable/components/DataTableCore.tsx +200 -561
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
- package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
- package/src/components/DataTable/components/DataTableModals.tsx +9 -1
- package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
- package/src/components/DataTable/components/EditFields.tsx +307 -0
- package/src/components/DataTable/components/EditableRow.tsx +9 -1
- package/src/components/DataTable/components/EmptyState.tsx +10 -0
- package/src/components/DataTable/components/FilterRow.tsx +12 -0
- package/src/components/DataTable/components/GroupHeader.tsx +12 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
- package/src/components/DataTable/components/ImportModal.tsx +7 -0
- package/src/components/DataTable/components/LoadingState.tsx +6 -0
- package/src/components/DataTable/components/PaginationControls.tsx +16 -1
- package/src/components/DataTable/components/RowComponent.tsx +391 -0
- package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
- package/src/components/DataTable/components/cellValueUtils.ts +40 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
- package/src/components/DataTable/context/DataTableContext.tsx +50 -0
- package/src/components/DataTable/core/ColumnFactory.ts +31 -0
- package/src/components/DataTable/core/DataTableContext.tsx +32 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
- package/src/components/DataTable/styles.ts +6 -6
- package/src/components/DataTable/types.ts +6 -10
- package/src/components/DataTable/utils/a11yUtils.ts +7 -0
- package/src/components/DataTable/utils/debugTools.ts +18 -113
- package/src/components/DataTable/utils/errorHandling.ts +12 -0
- package/src/components/DataTable/utils/exportUtils.ts +9 -0
- package/src/components/DataTable/utils/flexibleImport.ts +12 -48
- package/src/components/DataTable/utils/paginationUtils.ts +8 -0
- package/src/components/DataTable/utils/performanceUtils.ts +5 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
- package/src/components/Dialog/Dialog.tsx +8 -7
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/EventSelector/EventSelector.tsx +4 -1
- package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
- package/src/components/FileDisplay/FileDisplay.tsx +32 -18
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +15 -12
- package/src/components/Form/Form.test.tsx +36 -15
- package/src/components/Form/Form.tsx +31 -26
- package/src/components/Header/Header.tsx +22 -11
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +36 -34
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +42 -42
- package/src/components/LoginForm/LoginForm.tsx +12 -8
- package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
- package/src/components/PaceAppLayout/README.md +1 -1
- package/src/components/PaceAppLayout/test-setup.tsx +1 -2
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
- package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +95 -438
- package/src/components/Select/context.ts +23 -0
- package/src/components/Select/hooks/useSelectEvents.ts +87 -0
- package/src/components/Select/hooks/useSelectSearch.ts +91 -0
- package/src/components/Select/hooks/useSelectState.ts +104 -0
- package/src/components/Select/index.ts +9 -1
- package/src/components/Select/types.ts +123 -0
- package/src/components/Select/utils/text.ts +26 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +27 -29
- package/src/components/Toast/Toast.tsx +5 -1
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +22 -19
- package/src/components/index.ts +2 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +5 -1
- package/src/hooks/public/usePublicEventLogo.ts +5 -1
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +5 -1
- package/src/hooks/services/useAuth.ts +32 -0
- package/src/hooks/services/useCurrentEvent.ts +6 -0
- package/src/hooks/services/useCurrentOrganisation.ts +6 -0
- package/src/hooks/useDataTableState.ts +8 -18
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +4 -0
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +16 -2
- package/src/hooks/useFocusTrap.ts +7 -4
- package/src/hooks/useFormDialog.ts +8 -7
- package/src/hooks/useInactivityTracker.ts +4 -1
- package/src/hooks/useKeyboardShortcuts.ts +4 -0
- package/src/hooks/useOrganisationPermissions.ts +4 -0
- package/src/hooks/useOrganisationSecurity.ts +4 -0
- package/src/hooks/usePerformanceMonitor.ts +4 -0
- package/src/hooks/usePermissionCache.ts +8 -1
- package/src/hooks/useQueryCache.ts +12 -1
- package/src/hooks/useSessionRestoration.ts +4 -0
- package/src/hooks/useStorage.ts +4 -0
- package/src/hooks/useToast.ts +3 -3
- package/src/index.ts +2 -1
- package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
- package/src/providers/services/AuthServiceProvider.tsx +18 -0
- package/src/providers/services/EventServiceProvider.tsx +18 -0
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +14 -5
- package/src/rbac/api.ts +100 -67
- package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.tsx +5 -2
- package/src/rbac/components/PagePermissionGuard.tsx +158 -18
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +6 -2
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +21 -6
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
- package/src/rbac/engine.ts +38 -14
- package/src/rbac/hooks/permissions/index.ts +7 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
- package/src/rbac/hooks/permissions/useCan.ts +347 -0
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
- package/src/rbac/hooks/useCan.test.ts +71 -64
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +33 -13
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.ts +212 -61
- package/src/rbac/types.ts +8 -0
- package/src/theming/__tests__/parseEventColours.test.ts +6 -9
- package/src/theming/parseEventColours.ts +5 -19
- package/src/types/vitest-globals.d.ts +51 -26
- package/src/utils/__mocks__/supabaseMock.ts +1 -3
- package/src/utils/__tests__/formatting.unit.test.ts +4 -4
- package/src/utils/__tests__/index.unit.test.ts +2 -2
- package/src/utils/audit/audit.ts +0 -3
- package/src/utils/core/cn.ts +1 -1
- package/src/utils/file-reference/index.ts +53 -1
- package/src/utils/formatting/formatting.ts +8 -18
- package/src/utils/index.ts +0 -1
- package/src/utils/security/secureDataAccess.test.ts +31 -20
- package/src/utils/security/secureDataAccess.ts +4 -3
- package/dist/chunk-6C4YBBJM.js +0 -628
- package/dist/chunk-6C4YBBJM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js.map +0 -1
- package/dist/chunk-7FLMSG37.js 2.map +0 -1
- package/dist/chunk-7FLMSG37.js.map +0 -1
- package/dist/chunk-BC4IJKSL.js.map +0 -1
- package/dist/chunk-E3SPN4VZ.js +0 -12917
- package/dist/chunk-E3SPN4VZ.js.map +0 -1
- package/dist/chunk-E66EQZE6 5.js +0 -37
- package/dist/chunk-E66EQZE6.js 2.map +0 -1
- package/dist/chunk-HWIIPPNI.js.map +0 -1
- package/dist/chunk-I7PSE6JW 5.js +0 -191
- package/dist/chunk-I7PSE6JW.js 2.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-IIELH4DL.js.map +0 -1
- package/dist/chunk-KNC55RTG.js 5.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js 5.map +0 -1
- package/dist/chunk-LFNCN2SP.js +0 -412
- package/dist/chunk-LFNCN2SP.js 2.map +0 -1
- package/dist/chunk-LFNCN2SP.js.map +0 -1
- package/dist/chunk-LMC26NLJ 2.js +0 -84
- package/dist/chunk-NOAYCWCX.js +0 -4993
- package/dist/chunk-NOAYCWCX.js.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js.map +0 -1
- package/dist/chunk-QXHPKYJV 3.js +0 -113
- package/dist/chunk-R77UEZ4E.js +0 -68
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
- package/dist/chunk-XNXXZ43G.js.map +0 -1
- package/dist/chunk-ZSAAAMVR 6.js +0 -25
- package/dist/components.js 5.map +0 -1
- package/dist/styles/index 2.js +0 -12
- package/dist/styles/index.js 5.map +0 -1
- package/dist/theming/runtime 5.js +0 -19
- package/dist/theming/runtime.js 5.map +0 -1
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -666
- /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
- /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
- /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
- /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
- /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
- /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/index.ts +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build decision logic for documentation generation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, statSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Aggressive pre-check: Should we run TypeDoc at all?
|
|
12
|
+
* This checks source file hashes BEFORE running TypeDoc to avoid unnecessary runs
|
|
13
|
+
*/
|
|
14
|
+
export function shouldRunTypeDoc(config) {
|
|
15
|
+
const {
|
|
16
|
+
cache,
|
|
17
|
+
docsDir,
|
|
18
|
+
repoRoot,
|
|
19
|
+
docsRelevantPaths,
|
|
20
|
+
srcDir,
|
|
21
|
+
shouldSkipDueToCleanGitState,
|
|
22
|
+
primeCacheFromExistingDocs,
|
|
23
|
+
getSourceFileHashes,
|
|
24
|
+
hasSourceChanged,
|
|
25
|
+
getExistingDocHashes,
|
|
26
|
+
hashesMatch
|
|
27
|
+
} = config;
|
|
28
|
+
|
|
29
|
+
// If no cache, must run
|
|
30
|
+
if (cache.lastBuildTime === 0) {
|
|
31
|
+
if (shouldSkipDueToCleanGitState(repoRoot, docsDir, docsRelevantPaths)) {
|
|
32
|
+
console.log('⏭️ Skipping TypeDoc - no cache yet but git shows no relevant source changes.');
|
|
33
|
+
console.log(' Reason: Using checked-in docs since source tree matches HEAD');
|
|
34
|
+
console.log(' Action: Priming docs cache from checked-in files for future runs');
|
|
35
|
+
primeCacheFromExistingDocs({
|
|
36
|
+
cacheFile: config.cacheFile,
|
|
37
|
+
docsDir: config.docsDir,
|
|
38
|
+
srcDir: config.srcDir,
|
|
39
|
+
getLatestSourceModTime: config.getLatestSourceModTime,
|
|
40
|
+
getLatestDocModTime: config.getLatestDocModTime,
|
|
41
|
+
getExistingDocHashes: config.getExistingDocHashes,
|
|
42
|
+
getSourceFileHashes: config.getSourceFileHashes
|
|
43
|
+
});
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
console.log('📝 No cache found, running TypeDoc...');
|
|
47
|
+
console.log(' Reason: First run - no cache exists');
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// If docs don't exist, must run
|
|
52
|
+
if (!existsSync(docsDir)) {
|
|
53
|
+
console.log('📝 Documentation directory not found, running TypeDoc...');
|
|
54
|
+
console.log(' Reason: Documentation directory missing');
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check source file hashes - most reliable check
|
|
59
|
+
console.log('🔍 Checking source file hashes...');
|
|
60
|
+
const currentSourceHashes = getSourceFileHashes(srcDir);
|
|
61
|
+
const cachedSourceHashes = cache.sourceFileHashes || {};
|
|
62
|
+
|
|
63
|
+
console.log(` Current source files: ${currentSourceHashes.size}`);
|
|
64
|
+
console.log(` Cached source files: ${Object.keys(cachedSourceHashes).length}`);
|
|
65
|
+
|
|
66
|
+
if (hasSourceChanged(currentSourceHashes, cachedSourceHashes)) {
|
|
67
|
+
// Find which files changed
|
|
68
|
+
const changedFiles = [];
|
|
69
|
+
for (const [relativePath, currentHash] of currentSourceHashes.entries()) {
|
|
70
|
+
const cachedHash = cachedSourceHashes[relativePath];
|
|
71
|
+
if (cachedHash !== currentHash) {
|
|
72
|
+
changedFiles.push(relativePath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
console.log('📝 Source files have changed (hash comparison), running TypeDoc...');
|
|
76
|
+
if (changedFiles.length > 0 && changedFiles.length <= 10) {
|
|
77
|
+
console.log(` Changed files: ${changedFiles.slice(0, 5).join(', ')}${changedFiles.length > 5 ? ` ... and ${changedFiles.length - 5} more` : ''}`);
|
|
78
|
+
} else if (changedFiles.length > 10) {
|
|
79
|
+
console.log(` Changed files: ${changedFiles.length} files modified`);
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Source hasn't changed - check if docs match cache
|
|
85
|
+
console.log('🔍 Checking documentation file hashes...');
|
|
86
|
+
const currentDocHashes = getExistingDocHashes(docsDir);
|
|
87
|
+
const cachedDocHashes = cache.fileHashes || {};
|
|
88
|
+
|
|
89
|
+
console.log(` Current doc files: ${currentDocHashes.size}`);
|
|
90
|
+
console.log(` Cached doc files: ${Object.keys(cachedDocHashes).length}`);
|
|
91
|
+
|
|
92
|
+
if (hashesMatch(currentDocHashes, cachedDocHashes)) {
|
|
93
|
+
console.log('✅ Source unchanged and docs match cache - skipping TypeDoc entirely');
|
|
94
|
+
console.log(' Reason: No source changes detected and documentation is up to date');
|
|
95
|
+
return false; // Skip TypeDoc!
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Docs don't match cache but source unchanged - refresh cache snapshot instead of regenerating
|
|
99
|
+
const mismatchedFiles = [];
|
|
100
|
+
for (const [relativePath, currentHash] of currentDocHashes.entries()) {
|
|
101
|
+
const cachedHash = cachedDocHashes[relativePath];
|
|
102
|
+
if (cachedHash !== currentHash) {
|
|
103
|
+
mismatchedFiles.push(relativePath);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
console.log('⚠️ Source unchanged but docs don\'t match cache - refreshing cache from disk');
|
|
107
|
+
console.log(` Mismatched files: ${mismatchedFiles.length} files don't match cache`);
|
|
108
|
+
if (mismatchedFiles.length <= 5) {
|
|
109
|
+
console.log(` Files: ${mismatchedFiles.join(', ')}`);
|
|
110
|
+
}
|
|
111
|
+
primeCacheFromExistingDocs(config);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Check if any source files have changed since last build
|
|
117
|
+
*/
|
|
118
|
+
export function needsRebuild(config) {
|
|
119
|
+
const {
|
|
120
|
+
cache,
|
|
121
|
+
packageRoot,
|
|
122
|
+
docsDir,
|
|
123
|
+
srcDir,
|
|
124
|
+
getLatestSourceModTime,
|
|
125
|
+
getLatestDocModTime,
|
|
126
|
+
getExistingDocHashes
|
|
127
|
+
} = config;
|
|
128
|
+
|
|
129
|
+
const ignorePatterns = [
|
|
130
|
+
/\.test\.(ts|tsx)$/,
|
|
131
|
+
/\.spec\.(ts|tsx)$/,
|
|
132
|
+
/__tests__/,
|
|
133
|
+
/\/test\//,
|
|
134
|
+
/\/tests\//
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const currentSourceModTime = getLatestSourceModTime(srcDir, ignorePatterns);
|
|
138
|
+
const currentDocModTime = getLatestDocModTime(docsDir);
|
|
139
|
+
|
|
140
|
+
// If docs don't exist, we need to build
|
|
141
|
+
if (!existsSync(docsDir) || currentDocModTime === 0) {
|
|
142
|
+
console.log('📝 Documentation directory not found or empty, building...');
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check if typedoc.json has changed
|
|
147
|
+
const typedocConfigPath = join(packageRoot, 'typedoc.json');
|
|
148
|
+
if (existsSync(typedocConfigPath)) {
|
|
149
|
+
const configStats = statSync(typedocConfigPath);
|
|
150
|
+
if (cache.lastBuildTime > 0 && configStats.mtimeMs > cache.lastBuildTime) {
|
|
151
|
+
console.log('📝 TypeDoc configuration has changed, rebuilding...');
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
if (currentDocModTime > 0 && configStats.mtimeMs > currentDocModTime) {
|
|
155
|
+
console.log('📝 TypeDoc configuration is newer than docs, rebuilding...');
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Check entry point file (what TypeDoc actually uses)
|
|
161
|
+
const entryPointPath = join(packageRoot, 'src', 'index.ts');
|
|
162
|
+
if (existsSync(entryPointPath)) {
|
|
163
|
+
const entryStats = statSync(entryPointPath);
|
|
164
|
+
if (cache.lastBuildTime > 0 && entryStats.mtimeMs > cache.lastBuildTime) {
|
|
165
|
+
console.log('📝 Entry point file has changed, rebuilding...');
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
if (currentDocModTime > 0 && entryStats.mtimeMs > currentDocModTime) {
|
|
169
|
+
console.log('📝 Entry point file is newer than docs, rebuilding...');
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If source files are newer than docs, we need to rebuild
|
|
175
|
+
if (currentSourceModTime > currentDocModTime) {
|
|
176
|
+
console.log('📝 Source files are newer than documentation, rebuilding...');
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If cache indicates a rebuild is needed (e.g., after a clean)
|
|
181
|
+
// Only check cache if we have a valid cache entry
|
|
182
|
+
if (cache.lastBuildTime > 0) {
|
|
183
|
+
// Check if source files have changed since last build
|
|
184
|
+
const sourceChanged = currentSourceModTime > cache.sourceModTime;
|
|
185
|
+
|
|
186
|
+
// Check if docs are newer than the last build time (meaning they were just built)
|
|
187
|
+
const docsJustBuilt = currentDocModTime > cache.lastBuildTime - 1000; // 1 second tolerance
|
|
188
|
+
|
|
189
|
+
if (sourceChanged) {
|
|
190
|
+
console.log('📝 Source files have changed since last build, rebuilding...');
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// If docs were just built (within last second), skip rebuild to avoid double-building
|
|
195
|
+
if (docsJustBuilt) {
|
|
196
|
+
console.log('✅ Documentation was just built, skipping rebuild to avoid double-build');
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Check file-level hashes if available
|
|
201
|
+
if (cache.fileHashes && Object.keys(cache.fileHashes).length > 0) {
|
|
202
|
+
const currentHashes = getExistingDocHashes(docsDir);
|
|
203
|
+
let filesChanged = false;
|
|
204
|
+
|
|
205
|
+
// Check if any file hashes changed
|
|
206
|
+
for (const [relativePath, cachedHash] of Object.entries(cache.fileHashes)) {
|
|
207
|
+
const currentHash = currentHashes.get(relativePath);
|
|
208
|
+
if (currentHash !== cachedHash) {
|
|
209
|
+
filesChanged = true;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Check if any new files were added
|
|
215
|
+
if (!filesChanged && currentHashes.size !== Object.keys(cache.fileHashes).length) {
|
|
216
|
+
filesChanged = true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!filesChanged && !sourceChanged) {
|
|
220
|
+
console.log('✅ Documentation is up to date (file hashes match cache), skipping rebuild');
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// If cache exists and source hasn't changed, we're good
|
|
226
|
+
console.log('✅ Documentation is up to date (cache valid), skipping rebuild');
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// No cache exists - compare source vs docs directly
|
|
231
|
+
if (currentSourceModTime <= currentDocModTime) {
|
|
232
|
+
console.log('✅ Documentation is up to date, skipping rebuild');
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Fallback: rebuild if we can't determine
|
|
237
|
+
console.log('📝 Unable to determine if rebuild needed, rebuilding to be safe...');
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cache utilities for documentation build
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Load the cache file
|
|
11
|
+
*/
|
|
12
|
+
export function loadCache(cacheFile) {
|
|
13
|
+
if (!existsSync(cacheFile)) {
|
|
14
|
+
return {
|
|
15
|
+
lastBuildTime: 0,
|
|
16
|
+
sourceModTime: 0,
|
|
17
|
+
docModTime: 0,
|
|
18
|
+
fileHashes: {},
|
|
19
|
+
sourceFileHashes: {}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const content = readFileSync(cacheFile, 'utf-8');
|
|
25
|
+
const cache = JSON.parse(content);
|
|
26
|
+
// Ensure fileHashes exists for backward compatibility
|
|
27
|
+
if (!cache.fileHashes) {
|
|
28
|
+
cache.fileHashes = {};
|
|
29
|
+
}
|
|
30
|
+
if (!cache.sourceFileHashes) {
|
|
31
|
+
cache.sourceFileHashes = {};
|
|
32
|
+
}
|
|
33
|
+
return cache;
|
|
34
|
+
} catch (err) {
|
|
35
|
+
return {
|
|
36
|
+
lastBuildTime: 0,
|
|
37
|
+
sourceModTime: 0,
|
|
38
|
+
docModTime: 0,
|
|
39
|
+
fileHashes: {},
|
|
40
|
+
sourceFileHashes: {}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Save the cache file
|
|
47
|
+
*/
|
|
48
|
+
export function saveCache(cacheFile, cache) {
|
|
49
|
+
// Ensure fileHashes is always present
|
|
50
|
+
if (!cache.fileHashes) {
|
|
51
|
+
cache.fileHashes = {};
|
|
52
|
+
}
|
|
53
|
+
if (!cache.sourceFileHashes) {
|
|
54
|
+
cache.sourceFileHashes = {};
|
|
55
|
+
}
|
|
56
|
+
writeFileSync(cacheFile, JSON.stringify(cache, null, 2), 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Prime the docs cache using the currently checked-in documentation.
|
|
61
|
+
* This lets future runs rely on hash comparisons even if git status is dirty.
|
|
62
|
+
*/
|
|
63
|
+
export function primeCacheFromExistingDocs(config) {
|
|
64
|
+
const {
|
|
65
|
+
cacheFile,
|
|
66
|
+
docsDir,
|
|
67
|
+
srcDir,
|
|
68
|
+
getLatestSourceModTime,
|
|
69
|
+
getLatestDocModTime,
|
|
70
|
+
getExistingDocHashes,
|
|
71
|
+
getSourceFileHashes
|
|
72
|
+
} = config;
|
|
73
|
+
|
|
74
|
+
const currentDocHashes = getExistingDocHashes(docsDir);
|
|
75
|
+
const currentSourceHashes = getSourceFileHashes(srcDir);
|
|
76
|
+
|
|
77
|
+
const docHashesObj = {};
|
|
78
|
+
for (const [relativePath, hash] of currentDocHashes.entries()) {
|
|
79
|
+
docHashesObj[relativePath] = hash;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const sourceHashesObj = {};
|
|
83
|
+
for (const [relativePath, hash] of currentSourceHashes.entries()) {
|
|
84
|
+
sourceHashesObj[relativePath] = hash;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const ignorePatterns = [
|
|
88
|
+
/\.test\.(ts|tsx)$/,
|
|
89
|
+
/\.spec\.(ts|tsx)$/,
|
|
90
|
+
/__tests__/,
|
|
91
|
+
/\/test\//,
|
|
92
|
+
/\/tests\//
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
const cache = {
|
|
96
|
+
lastBuildTime: Date.now(),
|
|
97
|
+
sourceModTime: getLatestSourceModTime(srcDir, ignorePatterns),
|
|
98
|
+
docModTime: getLatestDocModTime(docsDir),
|
|
99
|
+
fileHashes: docHashesObj,
|
|
100
|
+
sourceFileHashes: sourceHashesObj
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
saveCache(cacheFile, cache);
|
|
104
|
+
}
|
|
105
|
+
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Content normalization utilities for documentation comparison
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Sort markdown list items for deterministic comparison
|
|
12
|
+
*/
|
|
13
|
+
export function sortMarkdownListItems(text) {
|
|
14
|
+
// Match markdown list sections (lines starting with - or *)
|
|
15
|
+
const lines = text.split('\n');
|
|
16
|
+
const sortedLines = [];
|
|
17
|
+
let currentList = [];
|
|
18
|
+
let inList = false;
|
|
19
|
+
|
|
20
|
+
for (const line of lines) {
|
|
21
|
+
const isListItem = /^\s*[-*]\s+/.test(line);
|
|
22
|
+
|
|
23
|
+
if (isListItem) {
|
|
24
|
+
if (!inList && currentList.length > 0) {
|
|
25
|
+
// Flush previous non-list content
|
|
26
|
+
sortedLines.push(...currentList);
|
|
27
|
+
currentList = [];
|
|
28
|
+
}
|
|
29
|
+
inList = true;
|
|
30
|
+
currentList.push(line);
|
|
31
|
+
} else {
|
|
32
|
+
if (inList && currentList.length > 0) {
|
|
33
|
+
// Sort and flush list
|
|
34
|
+
currentList.sort();
|
|
35
|
+
sortedLines.push(...currentList);
|
|
36
|
+
currentList = [];
|
|
37
|
+
}
|
|
38
|
+
inList = false;
|
|
39
|
+
currentList.push(line);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Flush remaining content
|
|
44
|
+
if (currentList.length > 0) {
|
|
45
|
+
if (inList) {
|
|
46
|
+
currentList.sort();
|
|
47
|
+
}
|
|
48
|
+
sortedLines.push(...currentList);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return sortedLines.join('\n');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Normalize markdown link references for deterministic comparison
|
|
56
|
+
*/
|
|
57
|
+
export function normalizeMarkdownLinks(text) {
|
|
58
|
+
// Extract and sort link references [id]: url "title"
|
|
59
|
+
const linkRefPattern = /^\[([^\]]+)\]:\s*(.+)$/gm;
|
|
60
|
+
const links = [];
|
|
61
|
+
let match;
|
|
62
|
+
|
|
63
|
+
while ((match = linkRefPattern.exec(text)) !== null) {
|
|
64
|
+
links.push(match[0]);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (links.length > 0) {
|
|
68
|
+
// Sort links by ID
|
|
69
|
+
links.sort();
|
|
70
|
+
// Replace all link references with sorted version
|
|
71
|
+
let normalized = text.replace(linkRefPattern, 'LINKREF');
|
|
72
|
+
// Append sorted links at the end
|
|
73
|
+
normalized = normalized.replace(/LINKREF/g, () => links.shift() || 'LINKREF');
|
|
74
|
+
return normalized;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return text;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Normalize "Defined in" links emitted by TypeDoc so that branch/remote differences
|
|
82
|
+
* don't cause hash mismatches between environments.
|
|
83
|
+
*/
|
|
84
|
+
export function normalizeDefinedInLinks(text) {
|
|
85
|
+
const definedInPattern = /\[(packages\/core\/[^\]]+?:\d+)\]\((https?:\/\/[^(]+?#L\d+)\)/g;
|
|
86
|
+
return text.replace(definedInPattern, (_match, displayText) => displayText);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Normalize content for comparison (remove trailing whitespace, normalize line endings, version numbers, timestamps)
|
|
91
|
+
*/
|
|
92
|
+
export function normalizeContent(content) {
|
|
93
|
+
let normalized = content
|
|
94
|
+
.replace(/\r\n/g, '\n') // Normalize line endings
|
|
95
|
+
.replace(/\r/g, '\n') // Handle old Mac line endings
|
|
96
|
+
.replace(/[ \t]+$/gm, '') // Remove trailing spaces/tabs
|
|
97
|
+
.replace(/\n{3,}/g, '\n\n'); // Normalize multiple blank lines
|
|
98
|
+
|
|
99
|
+
// Remove version numbers from TypeDoc-generated content
|
|
100
|
+
// TypeDoc includes version like "@jmruthers/pace-core@0.5.158"
|
|
101
|
+
// We normalize this to "@jmruthers/pace-core@VERSION" so version changes don't trigger updates
|
|
102
|
+
// This allows docs to remain unchanged when only the version number changes
|
|
103
|
+
normalized = normalized.replace(/@jmruthers\/pace-core@[\d.]+/g, '@jmruthers/pace-core@VERSION');
|
|
104
|
+
normalized = normalized.replace(/version\s+[\d.]+/gi, 'version VERSION');
|
|
105
|
+
// Also handle any other version patterns that might appear
|
|
106
|
+
normalized = normalized.replace(/\b[\d]+\.[\d]+\.[\d]+/g, 'VERSION');
|
|
107
|
+
|
|
108
|
+
// Remove timestamps and dates that might be generated dynamically
|
|
109
|
+
normalized = normalized.replace(/\d{4}-\d{2}-\d{2}/g, 'DATE'); // YYYY-MM-DD
|
|
110
|
+
normalized = normalized.replace(/\d{2}\/\d{2}\/\d{4}/g, 'DATE'); // MM/DD/YYYY
|
|
111
|
+
normalized = normalized.replace(/\d{2}:\d{2}:\d{2}/g, 'TIME'); // HH:MM:SS
|
|
112
|
+
normalized = normalized.replace(/Generated\s+on[^\n]*/gi, 'Generated on DATE');
|
|
113
|
+
normalized = normalized.replace(/Last\s+updated[^\n]*/gi, 'Last updated DATE');
|
|
114
|
+
normalized = normalized.replace(/Updated\s+[^\n]*/gi, 'Updated DATE');
|
|
115
|
+
|
|
116
|
+
// Remove any git commit hashes or SHAs that might appear
|
|
117
|
+
normalized = normalized.replace(/\b[0-9a-f]{7,40}\b/gi, 'HASH');
|
|
118
|
+
|
|
119
|
+
// Remove any ISO timestamps
|
|
120
|
+
normalized = normalized.replace(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[.\d]*Z?/g, 'TIMESTAMP');
|
|
121
|
+
|
|
122
|
+
// Normalize whitespace more aggressively
|
|
123
|
+
normalized = normalized.replace(/[ \t]+/g, ' '); // Multiple spaces/tabs to single space
|
|
124
|
+
normalized = normalized.replace(/ \n/g, '\n'); // Remove trailing spaces before newlines
|
|
125
|
+
|
|
126
|
+
// Sort markdown lists for deterministic comparison
|
|
127
|
+
normalized = sortMarkdownListItems(normalized);
|
|
128
|
+
|
|
129
|
+
// Normalize markdown link references
|
|
130
|
+
normalized = normalizeMarkdownLinks(normalized);
|
|
131
|
+
|
|
132
|
+
// Normalize "Defined in" GitHub links
|
|
133
|
+
normalized = normalizeDefinedInLinks(normalized);
|
|
134
|
+
|
|
135
|
+
return normalized.trim();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get current package version from package.json
|
|
140
|
+
*/
|
|
141
|
+
export function getPackageVersion(packageRoot) {
|
|
142
|
+
try {
|
|
143
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
144
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
145
|
+
return packageJson.version || '';
|
|
146
|
+
} catch (err) {
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* File system utilities for documentation build
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, statSync, readdirSync } from 'fs';
|
|
8
|
+
import { join, relative } from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Recursively scan directory for files matching pattern
|
|
12
|
+
*/
|
|
13
|
+
export function scanDirectory(dir, extensions, ignorePatterns = [], baseDir = null) {
|
|
14
|
+
const files = [];
|
|
15
|
+
const base = baseDir || dir;
|
|
16
|
+
|
|
17
|
+
function scan(currentDir) {
|
|
18
|
+
if (!existsSync(currentDir)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const items = readdirSync(currentDir, { withFileTypes: true });
|
|
24
|
+
|
|
25
|
+
for (const item of items) {
|
|
26
|
+
const fullPath = join(currentDir, item.name);
|
|
27
|
+
|
|
28
|
+
// Skip ignored patterns - test against relative path from base
|
|
29
|
+
const shouldIgnore = ignorePatterns.length > 0 && ignorePatterns.some(pattern => {
|
|
30
|
+
const relativePath = relative(base, fullPath);
|
|
31
|
+
return pattern.test(relativePath) || pattern.test(item.name);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (shouldIgnore) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (item.isDirectory() && !item.name.startsWith('.') && item.name !== 'node_modules') {
|
|
39
|
+
scan(fullPath);
|
|
40
|
+
} else if (item.isFile()) {
|
|
41
|
+
const ext = item.name.substring(item.name.lastIndexOf('.'));
|
|
42
|
+
if (extensions.includes(ext)) {
|
|
43
|
+
files.push(fullPath);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
// Skip directories we can't read
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
scan(dir);
|
|
53
|
+
return files;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the most recent modification time of all source files
|
|
58
|
+
*/
|
|
59
|
+
export function getLatestSourceModTime(srcDir, ignorePatterns = []) {
|
|
60
|
+
const sourceFiles = scanDirectory(srcDir, ['.ts', '.tsx'], ignorePatterns, srcDir);
|
|
61
|
+
|
|
62
|
+
let latestTime = 0;
|
|
63
|
+
for (const filePath of sourceFiles) {
|
|
64
|
+
try {
|
|
65
|
+
const stats = statSync(filePath);
|
|
66
|
+
if (stats.mtimeMs > latestTime) {
|
|
67
|
+
latestTime = stats.mtimeMs;
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
// File might have been deleted, skip it
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return latestTime;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get the most recent modification time of generated docs
|
|
79
|
+
*/
|
|
80
|
+
export function getLatestDocModTime(docsDir) {
|
|
81
|
+
if (!existsSync(docsDir)) {
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const docFiles = scanDirectory(docsDir, ['.md']);
|
|
86
|
+
|
|
87
|
+
if (docFiles.length === 0) {
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let latestTime = 0;
|
|
92
|
+
for (const filePath of docFiles) {
|
|
93
|
+
try {
|
|
94
|
+
const stats = statSync(filePath);
|
|
95
|
+
if (stats.mtimeMs > latestTime) {
|
|
96
|
+
latestTime = stats.mtimeMs;
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
// File might have been deleted, skip it
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return latestTime;
|
|
104
|
+
}
|
|
105
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Git utilities for documentation build
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { existsSync } from 'fs';
|
|
9
|
+
import { scanDirectory } from './file-utils.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Determine if we're inside a git repository
|
|
13
|
+
*/
|
|
14
|
+
export function isGitRepository(repoRoot) {
|
|
15
|
+
try {
|
|
16
|
+
execSync('git rev-parse --is-inside-work-tree', {
|
|
17
|
+
cwd: repoRoot,
|
|
18
|
+
stdio: 'pipe'
|
|
19
|
+
});
|
|
20
|
+
return true;
|
|
21
|
+
} catch (err) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Check if git reports any relevant source changes
|
|
28
|
+
*/
|
|
29
|
+
export function hasGitTrackedSourceChanges(repoRoot, docsRelevantPaths) {
|
|
30
|
+
if (!isGitRepository(repoRoot)) {
|
|
31
|
+
return true; // Without git context, err on the side of rebuilding
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const status = execSync(`git status --porcelain -- ${docsRelevantPaths.join(' ')}`.trim(), {
|
|
36
|
+
cwd: repoRoot,
|
|
37
|
+
encoding: 'utf-8',
|
|
38
|
+
stdio: 'pipe'
|
|
39
|
+
}).trim();
|
|
40
|
+
|
|
41
|
+
return status.length > 0;
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.log('⚠️ Unable to determine git status for docs generation, running TypeDoc to be safe.');
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* If we don't have a cache yet but the repo is clean and docs exist, we can skip
|
|
50
|
+
*/
|
|
51
|
+
export function shouldSkipDueToCleanGitState(repoRoot, docsDir, docsRelevantPaths) {
|
|
52
|
+
if (!existsSync(docsDir)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const existingDocs = scanDirectory(docsDir, ['.md']);
|
|
57
|
+
if (existingDocs.length === 0) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (hasGitTrackedSourceChanges(repoRoot, docsRelevantPaths)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log('✅ Git working tree is clean for documentation-related sources.');
|
|
66
|
+
console.log(' Assuming checked-in docs are up to date, skipping TypeDoc run.');
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get git status of docs directory
|
|
72
|
+
*/
|
|
73
|
+
export function getGitStatus(packageRoot, directory) {
|
|
74
|
+
try {
|
|
75
|
+
const result = execSync(`git status --porcelain ${directory}`, {
|
|
76
|
+
cwd: packageRoot,
|
|
77
|
+
encoding: 'utf-8',
|
|
78
|
+
stdio: 'pipe'
|
|
79
|
+
});
|
|
80
|
+
return result.trim().split('\n').filter(line => line.trim());
|
|
81
|
+
} catch (err) {
|
|
82
|
+
// Not a git repo or git not available
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|