diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3237ac966baa..bc8bd10c78a9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ on: '**.cjs', 'config/.editorconfig', 'config/eslint/**', - 'scripts/lint.sh', + 'scripts/lint.ts', 'scripts/lintChanged.sh', '.watchmanconfig', '.imgbotconfig', diff --git a/config/eslint/eslint.config.mjs b/config/eslint/eslint.config.mjs index 69c9bf8d12c7..bba1bf78aa84 100644 --- a/config/eslint/eslint.config.mjs +++ b/config/eslint/eslint.config.mjs @@ -711,6 +711,18 @@ const config = defineConfig([ }, }, + { + // lint.ts is excluded from the root tsconfig because it needs @types/bun, so type-aware rules have to + // be pointed at the project that does own it. See scripts/tsconfig.json. + files: ['scripts/lint.ts'], + languageOptions: { + parserOptions: { + project: path.resolve(projectRoot, 'scripts/tsconfig.json'), + projectService: false, + }, + }, + }, + { files: ['tests/tooling/**/*.ts'], rules: { diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv index 6744e0c2a3c3..d4be4631b710 100644 --- a/config/eslint/eslint.seatbelt.tsv +++ b/config/eslint/eslint.seatbelt.tsv @@ -43,7 +43,6 @@ "../../scripts/generateTranslations.ts" "@typescript-eslint/no-unsafe-type-assertion" 8 "../../scripts/react-compiler-compliance-check.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../scripts/sentry/release-adoption-older-than.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../scripts/utils/CLI.ts" "@typescript-eslint/no-unsafe-type-assertion" 18 "../../scripts/utils/Git.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../scripts/utils/OpenAIUtils.ts" "@typescript-eslint/no-deprecated/this.client.beta.threads.create" 1 "../../scripts/utils/OpenAIUtils.ts" "@typescript-eslint/no-deprecated/this.client.beta.threads.messages.list" 1 @@ -53,7 +52,6 @@ "../../scripts/utils/TSCompilerUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../scripts/utils/Translator/TranslationPromptUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../server/stubs/react-native-reanimated.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../server/stubs/react-native-reanimated/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../server/victory-chart-renderer/src/initSkiaForCli.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/CONST/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/DeepLinkHandler.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -98,8 +96,6 @@ "../../src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/AutoCompleteSuggestions/index.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/AutoSubmitModal.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/components/Avatar.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/AvatarCropModal/AvatarCropModal.tsx" "no-restricted-imports" 1 "../../src/components/AvatarCropModal/ImageCropView.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/AvatarCropModal/Slider.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/AvatarSelector.tsx" "no-restricted-syntax" 2 @@ -128,8 +124,6 @@ "../../src/components/ConnectToNetSuiteFlow/index.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/ConnectToXeroFlow/index.native.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/ConnectToXeroFlow/index.tsx" "react-hooks/set-state-in-effect" 1 -"../../src/components/ContactPermissionModal/index.native.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 -"../../src/components/ContactPermissionModal/index.native.tsx" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 2 "../../src/components/CountryPicker/CountrySelectorModal.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/CountryPicker/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/DatePicker/CalendarPicker/MonthPickerModal.tsx" "react-hooks/set-state-in-effect" 1 @@ -156,15 +150,12 @@ "../../src/components/EmojiSuggestions.tsx" "no-restricted-syntax" 1 "../../src/components/EmptySelectionListContent.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/EnvironmentBadge.tsx" "no-restricted-syntax" 1 -"../../src/components/ExplanationModal.tsx" "no-restricted-syntax" 1 "../../src/components/FeedbackSurvey.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/FilePicker/index.native.tsx" "react-hooks/refs" 1 "../../src/components/FilePicker/index.tsx" "react-hooks/refs" 1 "../../src/components/FlatList/FlatList/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 4 "../../src/components/FlatList/FlatList/index.tsx" "react-hooks/refs" 1 "../../src/components/FlatList/hooks/useFlatListHandle.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 -"../../src/components/FlatList/hooks/useFlatListScrollKey.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 -"../../src/components/FocusModeNotification.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 "../../src/components/FocusTrap/FocusTrapContainerElement/index.web.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/FocusTrap/FocusTrapForScreen/index.web.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Form/FormProvider.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -262,12 +253,9 @@ "../../src/components/MultifactorAuthentication/config/scenarios/DefaultUserInterface.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Navigation/QuickCreationActionsBar/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Navigation/QuickCreationActionsBar/index.tsx" "no-restricted-imports" 1 -"../../src/components/Navigation/TopLevelNavigationTabBar/index.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/NumberWithSymbolForm.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/NumberWithSymbolForm.tsx" "react-hooks/set-state-in-effect" 2 "../../src/components/OfflineWithFeedback.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/components/OptionListContextProvider.tsx" "react-hooks/refs" 2 -"../../src/components/OptionListContextProvider.tsx" "react-hooks/set-state-in-effect" 3 "../../src/components/OptionRow.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/components/OptionRow.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/PDFView/PDFPasswordForm.tsx" "no-restricted-imports" 1 @@ -277,7 +265,6 @@ "../../src/components/ParentNavigationSubtitle.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Picker/BasePicker.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/components/Picker/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/PlanTypeSelector.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/PopoverMenu/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/PopoverMenu/index.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/PopoverProvider/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -295,7 +282,6 @@ "../../src/components/Reactions/MiniQuickEmojiReactions.tsx" "react-hooks/refs" 1 "../../src/components/ReceiptCropView/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/ReceiptHoverZoom/useReceiptHoverZoom.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/ReportActionAvatars/ReportActionAvatar.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/components/ReportActionAvatars/useReportPreviewSenderID.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/components/ReportActionItem/IssueCardMessage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/components/ReportActionItem/MoneyReportView.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -315,19 +301,12 @@ "../../src/components/Search/FilterComponents/ReportField/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/FilterComponents/SingleSelect.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/FilterComponents/TypeSelector.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/FilterDropdowns/CardSelectPopup.tsx" "react-hooks/set-state-in-effect" 1 -"../../src/components/Search/FilterDropdowns/CommonPopup.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/FilterDropdowns/DropdownButton.tsx" "no-restricted-imports" 1 "../../src/components/Search/FilterDropdowns/SortByPopup.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/FilterDropdowns/UserSelectPopup.tsx" "react-hooks/set-state-in-effect" 1 "../../src/components/Search/SearchAutocompleteInput.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/components/Search/SearchAutocompleteList.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/SearchBulkActionsButton.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/components/Search/SearchContextDefinitions.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/SearchDatePresetFilterBasePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/SearchFiltersAmountBase.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/SearchFiltersCurrencyBase.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/SearchFiltersParticipantsSelector.tsx" "@typescript-eslint/no-unsafe-type-assertion" 4 "../../src/components/Search/SearchList/ListItem/BaseListItemHeader.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/SearchList/ListItem/CardListItemHeader.tsx" "@typescript-eslint/no-unsafe-type-assertion" 4 "../../src/components/Search/SearchList/ListItem/ChatListItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -344,13 +323,10 @@ "../../src/components/Search/SearchList/ListItem/TransactionListItem/TransactionListItemWide.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/SearchList/ListItem/TransactionListItem/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 4 "../../src/components/Search/SearchList/ListItem/WithdrawalIDListItemHeader.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/components/Search/SearchMultipleSelectionPicker.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx" "no-restricted-imports" 1 "../../src/components/Search/SearchPageHeader/SearchAdvancedFiltersButton.tsx" "no-restricted-imports" 1 "../../src/components/Search/SearchPageHeader/SearchFilterBar.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 -"../../src/components/Search/SearchPageHeader/useSearchPageInput.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/components/Search/SearchPageHeader/useSearchPageInput.tsx" "react-hooks/set-state-in-effect" 2 "../../src/components/Search/SearchQueryProvider.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/components/Search/SearchRouter/SearchRouter.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/Search/SearchRouter/SearchRouterUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -381,7 +357,6 @@ "../../src/components/SidePanel/SidePanelOverlay.tsx" "no-restricted-syntax" 1 "../../src/components/SidePanel/SidePanelReport/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/SignInButtons/IconButton.tsx" "no-restricted-syntax" 1 -"../../src/components/SingleOptionSelector.tsx" "no-restricted-syntax" 1 "../../src/components/SkeletonViewContentLoader/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/components/StatePicker/StateSelectorModal.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/components/StatePicker/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -462,8 +437,6 @@ "../../src/hooks/useAutoCreateTrackWorkspace.ts" "no-restricted-imports" 1 "../../src/hooks/useAutoUpdateTimezone.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useAutocompleteSuggestions.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/hooks/useBasePopoverReactionList/index.ts" "no-restricted-syntax" 2 -"../../src/hooks/useBasePopoverReactionList/index.ts" "react-hooks/set-state-in-effect" 1 "../../src/hooks/useBulkDuplicateAction.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useBulkPayOptions.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/hooks/useCachedImageSource.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -514,7 +487,6 @@ "../../src/hooks/useResetBankAccountModal.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useResponsiveLayout/index.native.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useResponsiveLayout/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/hooks/useRestoreInputFocus/index.android.ts" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 "../../src/hooks/useRestoreWorkspacesTabOnNavigate.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useReviewDuplicatesNavigation.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useReviewDuplicatesNavigation.tsx" "react-hooks/set-state-in-effect" 1 @@ -529,7 +501,6 @@ "../../src/hooks/useSubPage/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/hooks/useTackInputFocus/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/hooks/useTextWithMiddleEllipsis.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/hooks/useTodos.ts" "@typescript-eslint/no-unsafe-type-assertion" 5 "../../src/hooks/useTransactionViolationOfWorkspace.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useViolations.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/hooks/useWindowDimensions/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -541,7 +512,6 @@ "../../src/libs/AccountingUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/AttendeeUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/libs/Avatars/InitialAvatars.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/libs/Avatars/PresetAvatarCatalog.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/libs/BankAccountUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/CardFeedUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 7 "../../src/libs/CardUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 13 @@ -622,7 +592,6 @@ "../../src/libs/Navigation/OnyxTabNavigator.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/libs/Navigation/PlatformStackNavigation/ScreenLayout.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/Navigation/PlatformStackNavigation/navigationOptions/animation/withAnimation.ts" "@typescript-eslint/no-unsafe-type-assertion" 6 -"../../src/libs/Navigation/guards/AIFeaturesPromoGuard.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/Navigation/guards/MigratedUserWelcomeModalGuard.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/Navigation/guards/OnboardingGuard.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts" "@typescript-eslint/no-deprecated/escape" 1 @@ -654,8 +623,6 @@ "../../src/libs/Navigation/helpers/useIsSidebarRouteActive.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/Navigation/linkingConfig/RELATIONS/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/libs/Navigation/linkingConfig/config.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/libs/Navigation/navigateAfterInteraction/index.ios.ts" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 -"../../src/libs/NavigationFocusReturn.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/libs/Network/LoadTestState.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/Network/SequentialQueue.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/Network/enhanceParameters.ts" "no-restricted-syntax" 1 @@ -691,7 +658,6 @@ "../../src/libs/QuickActionUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/ReceiptUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/ReportActionFollowupUtils/tokenizeForReveal.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 -"../../src/libs/ReportActionItemEventHandler/index.android.ts" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 "../../src/libs/ReportActionsUtils.ts" "@typescript-eslint/no-deprecated/reportAction.sequenceNumber" 1 "../../src/libs/ReportActionsUtils.ts" "@typescript-eslint/no-deprecated/reportAction?.originalMessage" 2 "../../src/libs/ReportActionsUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 109 @@ -890,7 +856,6 @@ "../../src/libs/actions/getCompanyCardBankConnection/index.tsx" "no-restricted-imports" 1 "../../src/libs/actions/getCompanyCardBankConnection/index.tsx" "no-restricted-syntax" 2 "../../src/libs/actions/replaceOptimisticReportWithActualReport.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/libs/actions/setTestReceipt/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/canFocusInputOnScreenFocus/index.ts" "no-restricted-syntax" 1 "../../src/libs/clearSelectedTextIfComposerBlurred/clearSelectedTextIfComposerBlurred.web.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/compoundParamsKey.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -906,7 +871,6 @@ "../../src/libs/filterArrayByMatch.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/focusComposerWithDelay/index.ts" "no-restricted-syntax" 1 "../../src/libs/focusComposerWithDelay/setTextInputSelection.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/libs/focusEditAfterCancelDelete/index.native.ts" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 "../../src/libs/getPlatform/index.ts" "no-restricted-syntax" 1 "../../src/libs/getReturnValue.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/hadTabNavigation.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -919,8 +883,6 @@ "../../src/libs/prepareRequestPayload/index.native.ts" "@typescript-eslint/no-unsafe-type-assertion" 5 "../../src/libs/prepareRequestPayload/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/sanitizeLogParams.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/libs/setShouldShowComposeInputKeyboardAware/index.ts" "no-restricted-syntax" 1 -"../../src/libs/setShouldShowComposeInputKeyboardAware/setShouldShowComposeInputKeyboardAwareBuilder.ts" "no-restricted-syntax" 1 "../../src/libs/telemetry/forwardLogsToSentry.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/libs/updateMultilineInputRange/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/AddPersonalBankAccountPage/substeps/AddressStep.tsx" "@typescript-eslint/no-unsafe-type-assertion" 6 @@ -951,9 +913,6 @@ "../../src/pages/DynamicRoomMembersPage.tsx" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 2 "../../src/pages/DynamicRoomMembersPage.tsx" "react-hooks/preserve-manual-memoization" 1 "../../src/pages/DynamicRoomMembersPage.tsx" "react-hooks/set-state-in-effect" 1 -"../../src/pages/EnablePayments/FeesAndTerms/FeesAndTerms.tsx" "no-restricted-syntax" 2 -"../../src/pages/EnablePayments/FeesAndTerms/FeesAndTerms.tsx" "rulesdir/no-default-id-values" 1 -"../../src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx" "react-hooks/set-state-in-effect" 1 "../../src/pages/EnablePayments/Wallet/PersonalInfo/substeps/DateOfBirthStep.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../src/pages/EnablePayments/Wallet/utils/getSubstepValues.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/EnablePayments/shared/IdologyQuestions.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -964,9 +923,6 @@ "../../src/pages/MultifactorAuthentication/RevokePage.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 "../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/OnboardingPrivateDomain/BaseOnboardingPrivateDomain.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/OnboardingWorkspaceConfirmation/BaseOnboardingWorkspaceConfirmation.tsx" "no-restricted-imports" 1 -"../../src/pages/OnboardingWorkspaceCurrency/BaseOnboardingWorkspaceCurrency.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx" "no-restricted-imports" 1 "../../src/pages/ProfilePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/ReimbursementAccount/AddressFormFields.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/ReimbursementAccount/EnterSignerInfo/subSteps/Address.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -1002,13 +958,8 @@ "../../src/pages/ReportDescriptionPage.tsx" "no-restricted-imports" 1 "../../src/pages/ReportDescriptionPage.tsx" "no-restricted-syntax" 1 "../../src/pages/ScheduleCall/ScheduleCallPage.tsx" "react-hooks/preserve-manual-memoization" 1 -"../../src/pages/Search/AdvancedSearchFilters.tsx" "@typescript-eslint/no-unsafe-type-assertion" 17 "../../src/pages/Search/EmptySearchView.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/Search/SavedSearchRenamePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersCardPage.tsx" "react-hooks/set-state-in-effect" 1 -"../../src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersReportFieldPage/ReportFieldDate.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersReportFieldPage/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersWorkspacePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/Search/SearchChangeApproverPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/Search/SearchEditMultiple/SearchEditMultipleTagPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/Search/SearchEditMultiple/SearchEditMultipleUtils.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 @@ -1026,15 +977,11 @@ "../../src/pages/TransactionDuplicate/DynamicConfirmationPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/TransactionDuplicate/DynamicConfirmationPage.tsx" "no-restricted-imports" 1 "../../src/pages/TransactionDuplicate/DynamicConfirmationPage.tsx" "react-hooks/refs" 12 -"../../src/pages/TransactionDuplicate/Review.tsx" "no-restricted-imports" 1 "../../src/pages/TransactionMerge/DynamicConfirmationPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/TransactionMerge/MergeTransactionItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/TransactionMerge/MergeTransactionsListContent.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/Travel/DynamicDomainSelectorPage.tsx" "no-restricted-imports" 1 -"../../src/pages/Travel/DynamicTravelTerms.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/Travel/DynamicTravelUpgrade.tsx" "no-restricted-imports" 1 -"../../src/pages/Travel/TravelUpgrade.tsx" "react-hooks/set-state-in-effect" 1 "../../src/pages/Travel/WorkspaceConfirmationForTravelPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/TripChatNameEditPage.tsx" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 1 "../../src/pages/UnreportedExpenseListItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -1060,7 +1007,6 @@ "../../src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 "../../src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx" "react-hooks/refs" 28 -"../../src/pages/inbox/report/ListBoundaryLoader.tsx" "react-hooks/set-state-in-effect" 1 "../../src/pages/inbox/report/ReactionList/HeaderReactionList.tsx" "no-restricted-syntax" 1 "../../src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/inbox/report/ReportActionCompose/ComposerWithSuggestions.tsx" "@typescript-eslint/no-unsafe-type-assertion" 5 @@ -1108,12 +1054,7 @@ "../../src/pages/iou/request/ParticipantSearchResults.tsx" "@typescript-eslint/no-unsafe-type-assertion" 4 "../../src/pages/iou/request/step/DistanceManualTabContent.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/iou/request/step/DynamicIOURequestEditReport.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 "../../src/pages/iou/request/step/DynamicIOURequestStepReport.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/pages/iou/request/step/DynamicIOURequestStepUpgrade.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 -"../../src/pages/iou/request/step/DynamicIOURequestStepUpgrade.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 -"../../src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/iou/request/step/IOURequestStepAmount.tsx" "react-hooks/set-state-in-effect" 1 @@ -1128,10 +1069,8 @@ "../../src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/iou/request/step/IOURequestStepScan/ReceiptView/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/iou/request/step/IOURequestStepScan/ReceiptView/index.tsx" "react-hooks/set-state-in-effect" 1 -"../../src/pages/iou/request/step/IOURequestStepScan/components/MobileWebCameraView.tsx" "react-hooks/immutability" 1 "../../src/pages/iou/request/step/IOURequestStepScan/components/NavigationAwareCamera/WebCamera.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/iou/request/step/IOURequestStepScan/components/ScanEditReceipt.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/iou/request/step/IOURequestStepScan/hooks/useMobileReceiptScan.ts" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 "../../src/pages/iou/request/step/IOURequestStepScan/hooks/useScanRouteParams.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/iou/request/step/IOURequestStepScan/utils/buildReceiptFiles.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/iou/request/step/IOURequestStepScan/utils/getFileSource.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -1153,15 +1092,10 @@ "../../src/pages/media/AttachmentModalScreen/routes/hooks/useReportAttachmentModalType.ts" "react-hooks/set-state-in-effect" 1 "../../src/pages/media/AttachmentModalScreen/routes/report/ReportAvatarModalContent.tsx" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 2 "../../src/pages/settings/AboutPage/AboutPage.tsx" "react-hooks/refs" 1 -"../../src/pages/settings/Agents/AgentsListRow.tsx" "no-restricted-imports" 1 "../../src/pages/settings/Agents/Fields/EditPromptPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/settings/Copilot/CopilotPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/settings/ExitSurvey/DynamicExitSurveyConfirmPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/settings/PaymentCard/ChangeCurrency/index.tsx" "no-restricted-syntax" 1 "../../src/pages/settings/Profile/AgentAIPromptSection.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/settings/Profile/Avatar/AvatarCapture/index.native.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/settings/Profile/Avatar/AvatarCapture/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../src/pages/settings/Profile/Avatar/EditUserAvatarContent.tsx" "no-restricted-imports" 1 "../../src/pages/settings/Profile/Contacts/DynamicContactMethodDetailsPage.tsx" "react-hooks/refs" 3 "../../src/pages/settings/Profile/Contacts/DynamicContactMethodDetailsPage.tsx" "react-hooks/set-state-in-effect" 3 "../../src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx" "react-hooks/set-state-in-effect" 1 @@ -1180,7 +1114,6 @@ "../../src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/settings/Security/AddDelegate/ConfirmDelegateValidateCodePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateValidateCodePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx" "@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions" 1 "../../src/pages/settings/Subscription/CardAuthenticationModal/index.tsx" "react-hooks/set-state-in-effect" 1 "../../src/pages/settings/Subscription/PaymentCard/ChangeBillingCurrency/index.tsx" "no-restricted-syntax" 1 "../../src/pages/settings/Subscription/PaymentCard/DynamicPaymentCardCurrencySelectorPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -1191,8 +1124,6 @@ "../../src/pages/settings/Wallet/EnableGlobalReimbursements/EnableGlobalReimbursementsAgreementsPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/settings/Wallet/EnableGlobalReimbursements/EnableGlobalReimbursementsBusinessPage/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/settings/Wallet/ExpensifyCardPage/index.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 2 -"../../src/pages/settings/Wallet/InternationalDepositAccount/PersonalInfo/substeps/AddressStep.tsx" "@typescript-eslint/no-unsafe-type-assertion" 6 -"../../src/pages/settings/Wallet/InternationalDepositAccount/PersonalInfo/substeps/AddressStep.tsx" "react-hooks/set-state-in-effect" 1 "../../src/pages/settings/Wallet/InternationalDepositAccount/subPages/Confirmation.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/settings/Wallet/InternationalDepositAccount/utils.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/settings/Wallet/PaymentMethodList.tsx" "@typescript-eslint/no-unsafe-type-assertion" 7 @@ -1232,8 +1163,6 @@ "../../src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/WorkspaceOverviewPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/workspace/WorkspaceOverviewSharePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/workspace/WorkspaceResetBankAccountModal.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 -"../../src/pages/workspace/WorkspaceResetBankAccountModal.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/accounting/AccountingContext/default.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/accounting/ClaimOfferPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/accounting/PolicyAccountingPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -1342,8 +1271,6 @@ "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx" "react-hooks/set-state-in-effect" 1 "../../src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 -"../../src/pages/workspace/expensifyCard/WorkspaceEditCardLimitPage.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 -"../../src/pages/workspace/expensifyCard/WorkspaceEditCardLimitTypePage.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1 "../../src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 @@ -1457,9 +1384,7 @@ "../../src/types/utils/htmlDivElementRef.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/types/utils/textRef.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/types/utils/viewRef.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/utils/SafeString.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/utils/createDummySharedValue.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/utils/keyboard/index.website.ts" "no-restricted-imports" 1 "../../src/utils/times.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../tests/actions/EnforceActionExportRestrictions.ts" "no-restricted-imports" 1 "../../tests/actions/IOU/CreateDraftTransactionTest.ts" "no-restricted-imports" 1 @@ -1492,9 +1417,7 @@ "../../tests/ui/ForYouSectionTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/ui/LocationPermissionModalTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/ui/MoneyRequestReportPreview.test.tsx" "no-restricted-imports" 1 -"../../tests/ui/ReportActionsViewTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 20 "../../tests/ui/ScanSkipConfirmationTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 -"../../tests/ui/SearchReportAvatarTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/ui/WorkEmailOnboarding.tsx" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/ui/WorkspaceCategoriesTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/ui/WorkspaceMoreFeaturesPageTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -1507,7 +1430,6 @@ "../../tests/unit/AvatarUtilsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/BulletListRendererTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/ButtonStyleUtilsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../tests/unit/CLIVariadicTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../tests/unit/CompanyCardExportTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/ContextMenuActionsCopyMessageTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/unit/CountryUtils.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 @@ -1519,14 +1441,12 @@ "../../tests/unit/HomePage/YourSpendSection/useYourSpendDataTest.ts" "no-restricted-imports" 1 "../../tests/unit/IOUUtilsTest.ts" "no-restricted-imports" 1 "../../tests/unit/ModifiedExpenseMessageTest.ts" "no-restricted-imports" 1 -"../../tests/unit/OptionListContextProviderTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 10 "../../tests/unit/QuickActionUtilsTest.ts" "no-restricted-imports" 2 "../../tests/unit/ReportNameUtilsTest.ts" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 3 "../../tests/unit/ReportPrimaryActionUtilsTest.ts" "no-restricted-imports" 1 "../../tests/unit/ReportSecondaryActionUtilsTest.ts" "no-restricted-imports" 2 "../../tests/unit/ReportTitleUtilsTest.ts" "no-restricted-imports" 1 "../../tests/unit/ReportUtilsTest.ts" "no-restricted-imports" 1 -"../../tests/unit/Search/SearchListRenderCountTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/Search/handleActionButtonPressTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/Search/searchTotalsLoadingDataTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/Search/useLiveRowCapabilitiesTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -1538,7 +1458,6 @@ "../../tests/unit/TelemetrySynchronizerTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/TranslateTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/WorkspaceReportFieldUtilsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../tests/unit/awaitStagingDeploysTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/unit/canEditFieldOfMoneyRequestTest.ts" "@typescript-eslint/no-deprecated/randomReportAction.originalMessage" 3 "../../tests/unit/cleanupAndNavigateAfterExpenseCreateTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/components/reportDetails/DynamicReportDetailsPageTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 @@ -1547,24 +1466,19 @@ "../../tests/unit/dismissModalAndOpenReportInInboxTabTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/unit/findUnusedStylesTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 3 "../../tests/unit/hooks/confirmAction.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../tests/unit/hooks/useHasAnyAdminExpensifyCardFeed.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../tests/unit/hooks/useTimeSensitiveCards.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/navigateAfterOnboardingTest.ts" "no-restricted-imports" 1 "../../tests/unit/navigateToWorkspacesPageTest.ts" "no-restricted-imports" 1 "../../tests/unit/pages/inbox/report/ReportActionEditMessageContext.test.tsx" "no-restricted-imports" 1 -"../../tests/unit/pages/settings/AgentsListRowTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../tests/unit/resolveSplitItemReportIDTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/resolveSplitMileageRateTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/sanitizeStringForJSONParseTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../tests/unit/useAccountTabIndicatorStatusTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9 "../../tests/unit/useCreateReportTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 9 -"../../tests/unit/useGroupDraftRestoreTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 14 "../../tests/unit/useMarkAsReadTest.ts" "no-restricted-imports" 1 "../../tests/unit/useSubPageTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../../tests/unit/useTodosTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 4 "../../tests/utils/createMock.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../tests/utils/getIsUsingFakeTimers.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 "../rsbuild/CustomVersionFilePlugin.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../rsbuild/ModuleInitTimingPlugin.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 "../rsbuild/rsbuild.common.ts" "@typescript-eslint/no-unsafe-type-assertion" 2 -"../rspack/RspackPreloadPlugin.ts" "@typescript-eslint/no-unsafe-type-assertion" 1 diff --git a/contributingGuides/LINTING.md b/contributingGuides/LINTING.md index 2412b1aa67e2..d7ec02c7a65e 100644 --- a/contributingGuides/LINTING.md +++ b/contributingGuides/LINTING.md @@ -124,7 +124,7 @@ Commit the updated `config/eslint/eslint.seatbelt.tsv` alongside the rename. The ## CI behavior -The [`ESLint check`](../.github/workflows/lint.yml) workflow runs `npm run lint`. In CI, `readOnly` is off (so seatbelt can write) and `SEATBELT_FROZEN=0` is exported from [`scripts/lint.sh`](../scripts/lint.sh) so GitHub Actions' auto-set `CI=true` doesn't flip seatbelt into frozen mode. +The [`ESLint check`](../.github/workflows/lint.yml) workflow runs `npm run lint`. In CI, `readOnly` is off (so seatbelt can write) and `SEATBELT_FROZEN=0` is exported from [`scripts/lint.ts`](../scripts/lint.ts) so GitHub Actions' auto-set `CI=true` doesn't flip seatbelt into frozen mode. - **PR runs:** counts go down → passes (TSV rewrite is ephemeral and thrown away with the runner). Counts go up without `SEATBELT_INCREASE` → fails with seatbelt's "exceeds allowed count" error. - **`push: main` runs:** same behavior, plus an extra step — if `config/eslint/eslint.seatbelt.tsv` changed, OSBotify commits the tightened baseline straight back to `main`. diff --git a/package.json b/package.json index 934b88a52842..1c4101cd6c03 100644 --- a/package.json +++ b/package.json @@ -46,11 +46,11 @@ "test:verbose": "TZ=utc NODE_OPTIONS=\"--experimental-vm-modules --max_old_space_size=4096\" JEST_VERBOSE=true jest", "test:debug": "TZ=utc NODE_OPTIONS='--inspect-brk --experimental-vm-modules' jest --runInBand", "perf-test": "NODE_OPTIONS=--experimental-vm-modules npx reassure", - "typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc && NODE_OPTIONS=--max_old_space_size=8192 tsc -p tests/tooling/tsconfig.json && NODE_OPTIONS=--max_old_space_size=8192 tsc -p server/tsconfig.json && NODE_OPTIONS=--max_old_space_size=8192 tsc -p server/victory-chart-renderer/tsconfig.json", - "typecheck-tsgo": "tsgo --noEmit --incremental --tsBuildInfoFile tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p tests/tooling/tsconfig.json --incremental --tsBuildInfoFile tests/tooling/tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p server/tsconfig.json --incremental --tsBuildInfoFile server/tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p server/victory-chart-renderer/tsconfig.json --incremental --tsBuildInfoFile server/victory-chart-renderer/tsconfig.tsgo.tsbuildinfo", - "lint": "./scripts/lint.sh", + "typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc && NODE_OPTIONS=--max_old_space_size=8192 tsc -p tests/tooling/tsconfig.json && NODE_OPTIONS=--max_old_space_size=8192 tsc -p server/tsconfig.json && NODE_OPTIONS=--max_old_space_size=8192 tsc -p server/victory-chart-renderer/tsconfig.json && NODE_OPTIONS=--max_old_space_size=8192 tsc -p scripts/tsconfig.json", + "typecheck-tsgo": "tsgo --noEmit --incremental --tsBuildInfoFile tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p tests/tooling/tsconfig.json --incremental --tsBuildInfoFile tests/tooling/tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p server/tsconfig.json --incremental --tsBuildInfoFile server/tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p server/victory-chart-renderer/tsconfig.json --incremental --tsBuildInfoFile server/victory-chart-renderer/tsconfig.tsgo.tsbuildinfo && tsgo --noEmit -p scripts/tsconfig.json --incremental --tsBuildInfoFile scripts/tsconfig.tsgo.tsbuildinfo", + "lint": "bun scripts/lint.ts", "lint-changed": "./scripts/lintChanged.sh", - "lint-watch": "onchange '**/*.{js,jsx,ts,tsx,mjs,cjs}' -- ./scripts/lint.sh {{changed}}", + "lint-watch": "onchange '**/*.{js,jsx,ts,tsx,mjs,cjs}' -- bun scripts/lint.ts {{changed}}", "eslint-report": "bun scripts/eslint-report.ts", "knip": "KNIP=true knip --include dependencies --exclude unlisted --no-exit-code --reporter compact", "knip:full": "KNIP=true knip --reporter compact", diff --git a/patches/eslint-seatbelt/details.md b/patches/eslint-seatbelt/details.md index 1c2f3f1d1754..7ae1081af0e5 100644 --- a/patches/eslint-seatbelt/details.md +++ b/patches/eslint-seatbelt/details.md @@ -38,3 +38,20 @@ - Upstream PR/issue: https://github.com/justjake/eslint-seatbelt/pull/29 - E/App issue: N/A - PR introducing patch: https://github.com/Expensify/App/pull/88566 + +### [eslint-seatbelt+0.1.3+003+readonly-type-declarations.patch](eslint-seatbelt+0.1.3+003+readonly-type-declarations.patch) + +- Reason: + + Patch 002 added the `readOnly` config option to the runtime and to `README.md`, + but never added it to the `SeatbeltConfig` TypeScript interface, so `SeatbeltConfig` + and the derived `SeatbeltArgs` type didn't know about it. Any consumer of + `eslint-seatbelt/api` that reads or sets `readOnly` (e.g. `scripts/lint.ts`, which + prunes baseline rows for deleted files using the same readOnly semantics as the rest + of the seatbelt baseline) failed to typecheck. This adds the missing `readOnly?: boolean` + field to both the `.d.ts` and `.d.mts` copies of the interface, matching the JSDoc + already shipped in `README.md` by patch 002. + +- Upstream PR/issue: N/A (the `readOnly` option itself is an Expensify-only patch, not upstream) +- E/App issue: N/A +- PR introducing patch: https://github.com/Expensify/App/pull/98665 diff --git a/patches/eslint-seatbelt/eslint-seatbelt+0.1.3+003+readonly-type-declarations.patch b/patches/eslint-seatbelt/eslint-seatbelt+0.1.3+003+readonly-type-declarations.patch new file mode 100644 index 000000000000..61fc5db8d6ae --- /dev/null +++ b/patches/eslint-seatbelt/eslint-seatbelt+0.1.3+003+readonly-type-declarations.patch @@ -0,0 +1,92 @@ +diff --git a/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.mts b/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.mts +index 9215119..88fa896 100644 +--- a/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.mts ++++ b/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.mts +@@ -298,6 +298,41 @@ interface SeatbeltConfig { + * ``` + */ + disable?: boolean; ++ /** ++ * When `true`, seatbelt validates error counts (still reporting increases) ++ * but never writes the seatbelt file. Keeps the worktree clean in local / ++ * editor runs; expect an authoritative updater (e.g. post-merge CI) to run ++ * with `readOnly: false`. ++ * ++ * Unlike `frozen`, does not turn decreases into errors. If both are set, ++ * `frozen` messaging is preserved and no write occurs. ++ * ++ * `SEATBELT_INCREASE` overrides this so intentional loosening is persisted. ++ * ++ * Defaults to `false`. ++ * ++ * Set via `SEATBELT_READ_ONLY` env var: ++ * ++ * ```bash ++ * SEATBELT_READ_ONLY=1 eslint ++ * ``` ++ * ++ * Or in ESLint config: ++ * ++ * ```js ++ * // in eslint.config.js ++ * const config = [ ++ * { ++ * settings: { ++ * seatbelt: { ++ * readOnly: !process.env.CI, ++ * } ++ * } ++ * } ++ * ] ++ * ``` ++ */ ++ readOnly?: boolean; + /** + * Suppress seatbelt's informational warning messages (e.g. "tend the garden", + * "thank you for fixing"). When enabled, seatbelt still downgrades errors to +diff --git a/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.ts b/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.ts +index 9215119..88fa896 100644 +--- a/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.ts ++++ b/node_modules/eslint-seatbelt/dist/SeatbeltConfig-CvuyHBlj.d.ts +@@ -298,6 +298,41 @@ interface SeatbeltConfig { + * ``` + */ + disable?: boolean; ++ /** ++ * When `true`, seatbelt validates error counts (still reporting increases) ++ * but never writes the seatbelt file. Keeps the worktree clean in local / ++ * editor runs; expect an authoritative updater (e.g. post-merge CI) to run ++ * with `readOnly: false`. ++ * ++ * Unlike `frozen`, does not turn decreases into errors. If both are set, ++ * `frozen` messaging is preserved and no write occurs. ++ * ++ * `SEATBELT_INCREASE` overrides this so intentional loosening is persisted. ++ * ++ * Defaults to `false`. ++ * ++ * Set via `SEATBELT_READ_ONLY` env var: ++ * ++ * ```bash ++ * SEATBELT_READ_ONLY=1 eslint ++ * ``` ++ * ++ * Or in ESLint config: ++ * ++ * ```js ++ * // in eslint.config.js ++ * const config = [ ++ * { ++ * settings: { ++ * seatbelt: { ++ * readOnly: !process.env.CI, ++ * } ++ * } ++ * } ++ * ] ++ * ``` ++ */ ++ readOnly?: boolean; + /** + * Suppress seatbelt's informational warning messages (e.g. "tend the garden", + * "thank you for fixing"). When enabled, seatbelt still downgrades errors to diff --git a/scripts/checkOnyxConnectBypass.ts b/scripts/checkOnyxConnectBypass.ts index f25b56bd0994..a5ade47cfe19 100644 --- a/scripts/checkOnyxConnectBypass.ts +++ b/scripts/checkOnyxConnectBypass.ts @@ -68,10 +68,14 @@ function findCandidateFiles(targets: string[]): string[] { } } -async function run(): Promise { - const candidates = findCandidateFiles(process.argv.slice(2)); +/** + * Checks `targets` for new Onyx.connect() ban bypasses, reporting any to stderr. + * Returns `true` if a new bypass was found (i.e. the caller should fail). + */ +async function checkOnyxConnectBypass(targets: string[]): Promise { + const candidates = findCandidateFiles(targets); if (candidates.length === 0) { - return; + return false; } const rule = await loadNoOnyxConnectRule(); @@ -93,7 +97,7 @@ async function run(): Promise { const results = await eslint.lintFiles(candidates); const newBypasses = findNewBypasses(collectSuppressedBans(results, projectRoot)); if (newBypasses.length === 0) { - return; + return false; } console.error('Onyx.connect() is banned and the ban cannot be bypassed with eslint-disable. Use the useOnyx() hook to read Onyx data instead.'); @@ -101,10 +105,21 @@ async function run(): Promise { for (const bypass of newBypasses) { console.error(` ${bypass.file}:${bypass.line}`); } - process.exitCode = 1; + return true; +} + +if (require.main === module) { + checkOnyxConnectBypass(process.argv.slice(2)) + .then((failed) => { + if (!failed) { + return; + } + process.exitCode = 1; + }) + .catch((error: unknown) => { + console.error(error instanceof Error ? error.message : error); + process.exitCode = 1; + }); } -run().catch((error: unknown) => { - console.error(error instanceof Error ? error.message : error); - process.exitCode = 1; -}); +export default checkOnyxConnectBypass; diff --git a/scripts/lint.sh b/scripts/lint.sh deleted file mode 100755 index 0d7253d26dd4..000000000000 --- a/scripts/lint.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -# Run ESLint with the repo's standard flags (memory ceiling, shared content -# cache, auto concurrency). Delegate target selection to the caller: -# -# ./scripts/lint.sh -> lint the whole repo -# ./scripts/lint.sh src/foo.ts ... -> lint just the given paths -# ./scripts/lint.sh --show-warnings ... -> include grandfathered seatbelt warnings in the output -# -# By default we pass `--quiet` to ESLint so only blocking errors are printed. -# eslint-seatbelt reclassifies grandfathered violations as warnings, so the -# default output mirrors what CI cares about. Pass `--show-warnings` to -# restore the full output (errors + warnings). - -set -euo pipefail - -# parse args -USE_CACHE=true -SHOW_WARNINGS=false -PASSTHROUGH_ARGS=() -for ARG in "$@"; do - case "$ARG" in - --no-cache) - USE_CACHE=false - ;; - --show-warnings) - SHOW_WARNINGS=true - ;; - *) - PASSTHROUGH_ARGS+=("$ARG") - ;; - esac -done - -# Preserve default behavior of linting the whole repo when no target is passed. -if [[ "${#PASSTHROUGH_ARGS[@]}" -eq 0 ]]; then - PASSTHROUGH_ARGS=(.) -fi - -# Build ESLint args -ESLINT_ARGS=() -if [[ "$USE_CACHE" == "true" ]]; then - ESLINT_ARGS+=( - --cache - --cache-location=node_modules/.cache/eslint - --cache-strategy content - ) -fi -if [[ "$SHOW_WARNINGS" == "false" ]]; then - ESLINT_ARGS+=(--quiet) -fi -# Type-aware linting loads the full TypeScript program in every worker (~12GB heap each on a -# cold cache), so hosts with limited memory need fewer workers with a larger heap rather than -# ESLint's auto worker count. Override via ESLINT_CONCURRENCY and NODE_OPTIONS together. -ESLINT_ARGS+=( - --concurrency="${ESLINT_CONCURRENCY:-auto}" - --no-warn-ignored - "${PASSTHROUGH_ARGS[@]}" -) - -# Run ESLint with the repo's default memory ceiling and seatbelt behavior. -NODE_OPTIONS="${NODE_OPTIONS:---max_old_space_size=8192}" \ -SEATBELT_FROZEN="${SEATBELT_FROZEN:-0}" \ - npx eslint "${ESLINT_ARGS[@]}" - -# Fail if a new inline eslint-disable bypasses the Onyx.connect() ban (rulesdir/no-onyx-connect), -# checking the same targets as ESLint above. Reached only when ESLint itself passes (set -e). -exec bun scripts/checkOnyxConnectBypass.ts "${PASSTHROUGH_ARGS[@]}" diff --git a/scripts/lint.ts b/scripts/lint.ts new file mode 100644 index 000000000000..76a5d7eb3488 --- /dev/null +++ b/scripts/lint.ts @@ -0,0 +1,113 @@ +#!/usr/bin/env bun + +/** + * Run ESLint with the repo's standard flags (memory ceiling, shared content + * cache, auto concurrency), then finish tightening the eslint-seatbelt baseline. + * Delegate target selection to the caller: + * + * bun scripts/lint.ts -> lint the whole repo + * bun scripts/lint.ts src/foo.ts ... -> lint just the given paths + * bun scripts/lint.ts --show-warnings ... -> include grandfathered seatbelt warnings in the output + * + * By default we pass `--quiet` to ESLint so only blocking errors are printed. + * eslint-seatbelt reclassifies grandfathered violations as warnings, so the + * default output mirrors what CI cares about. Pass `--show-warnings` to + * restore the full output (errors + warnings). + */ +import {$, file} from 'bun'; +import {SeatbeltArgs, SeatbeltFile} from 'eslint-seatbelt/api'; + +import checkOnyxConnectBypass from './checkOnyxConnectBypass'; + +const projectRoot = `${import.meta.dir}/..`; + +// parse args +let useCache = true; +let showWarnings = false; +const passthroughArgs: string[] = []; +for (const arg of process.argv.slice(2)) { + if (arg === '--no-cache') { + useCache = false; + } else if (arg === '--show-warnings') { + showWarnings = true; + } else { + passthroughArgs.push(arg); + } +} + +// Preserve default behavior of linting the whole repo when no target is passed. +const lintTargets = passthroughArgs.length > 0 ? passthroughArgs : ['.']; + +// Build ESLint args +const eslintArgs: string[] = []; +if (useCache) { + eslintArgs.push('--cache', '--cache-location=node_modules/.cache/eslint', '--cache-strategy', 'content'); +} +if (!showWarnings) { + eslintArgs.push('--quiet'); +} +// Type-aware linting loads the full TypeScript program in every worker (~12GB heap each on a +// cold cache), so hosts with limited memory need fewer workers with a larger heap rather than +// ESLint's auto worker count. Override via ESLINT_CONCURRENCY and NODE_OPTIONS together. +eslintArgs.push(`--concurrency=${process.env.ESLINT_CONCURRENCY ?? 'auto'}`, '--no-warn-ignored', ...lintTargets); + +const nodeOptions: string = process.env.NODE_OPTIONS ?? '--max_old_space_size=8192'; +const seatbeltFrozenEnv: string = process.env.SEATBELT_FROZEN ?? '0'; + +// Run ESLint with the repo's default memory ceiling and seatbelt behavior. +const eslintResult = await $`npx eslint ${eslintArgs}` + .cwd(projectRoot) + .env({...process.env, NODE_OPTIONS: nodeOptions, SEATBELT_FROZEN: seatbeltFrozenEnv}) + .nothrow(); +if (eslintResult.exitCode !== 0) { + process.exit(eslintResult.exitCode); +} + +/** Mirrors eslint-seatbelt's own boolean env var parsing: unset/empty is unset, "0"/"false"/"no" (case-insensitive) is false, anything else is true. */ +function readSeatbeltBooleanEnvVar(value: string | undefined): boolean | undefined { + if (value === undefined || value === '') { + return undefined; + } + return !['0', 'false', 'no'].includes(value.toLowerCase()); +} + +// eslint-seatbelt only rewrites the row for a file it actually lints, so a deleted or renamed +// file's row is never revisited and lingers in the baseline forever (a dead-code gap in +// eslint-seatbelt itself: https://github.com/justjake/eslint-seatbelt/issues/15). Finish the job +// by dropping rows for files that no longer exist, mirroring the same readOnly default as +// config/eslint/eslint.config.mjs and the same SEATBELT_READ_ONLY/SEATBELT_INCREASE/SEATBELT_DISABLE +// escape hatches eslint-seatbelt itself honors, so pruning never dirties a local worktree. +const seatbeltPath = `${projectRoot}/config/eslint/eslint.seatbelt.tsv`; +const isSeatbeltIncreaseSet = !!process.env.SEATBELT_INCREASE; +const seatbeltArgs = SeatbeltArgs.fromConfig({ + seatbeltFile: seatbeltPath, + disable: readSeatbeltBooleanEnvVar(process.env.SEATBELT_DISABLE) ?? false, + frozen: readSeatbeltBooleanEnvVar(seatbeltFrozenEnv) ?? false, + readOnly: isSeatbeltIncreaseSet ? false : (readSeatbeltBooleanEnvVar(process.env.SEATBELT_READ_ONLY) ?? !process.env.CI), +}); +if (!seatbeltArgs.disable) { + const seatbeltFile = SeatbeltFile.readSync(seatbeltPath); + const filenames = Array.from(seatbeltFile.filenames()); + const missingFilenames = (await Promise.all(filenames.map(async (filename) => ((await file(filename).exists()) ? undefined : filename)))).filter( + (filename): filename is string => filename !== undefined, + ); + + let removedCount = 0; + for (const filename of missingFilenames) { + if (seatbeltFile.removeFile(filename, seatbeltArgs)) { + removedCount++; + } + } + if (removedCount > 0) { + console.log(`eslint-seatbelt: removed ${removedCount} baseline row(s) for deleted files`); + if (!seatbeltArgs.frozen && !seatbeltArgs.readOnly) { + seatbeltFile.writeSync(); + } + } +} + +// Fail if a new inline eslint-disable bypasses the Onyx.connect() ban (rulesdir/no-onyx-connect), +// checking the same targets as ESLint above. Reached only when ESLint itself passes. +if (await checkOnyxConnectBypass(lintTargets)) { + process.exit(1); +} diff --git a/scripts/lintChanged.sh b/scripts/lintChanged.sh index ccf87cd3595b..997e2b7bc3fb 100755 --- a/scripts/lintChanged.sh +++ b/scripts/lintChanged.sh @@ -30,7 +30,7 @@ fi # Run eslint on the changed files, forwarding any user-provided flags if [[ -n "$GIT_DIFF_OUTPUT" ]] ; then # shellcheck disable=SC2086 # For multiple files in variable - exec "${TOP}/scripts/lint.sh" "$@" $GIT_DIFF_OUTPUT + exec bun "${TOP}/scripts/lint.ts" "$@" $GIT_DIFF_OUTPUT else info "No lintable files changed" fi diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index e06a1deec85a..9adfc766f02d 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -1,24 +1,24 @@ { + // Files listed below use Bun's `$` shell (or another Bun-only API), which needs `@types/bun`. Those types + // redeclare globals the app's own types already own (see tests/tooling/tsconfig.json for the same + // tradeoff), so this project confines them to just the files that need them. Everything else in scripts/ + // stays in the root project, where it sees the app's real types. + // + // This can't be widened to the whole scripts/ directory: several scripts (e.g. generateTranslations.ts, + // eslint-report.ts) import from @src/*, which transitively pulls in a large slice of the app. Under this + // project's narrower `types`, that slice loses access to ambient declarations the root project provides + // (asset module types, Onyx's generic augmentations, etc.) and re-typechecks with real errors — e.g. Onyx + // entries collapsing to `Record` and `@assets/*.svg` imports failing to resolve. + // + // To add a new Bun-shell script: add its filename to `files` below. + // + // `include: []` is required: `extends` inherits the root project's `include`, which would otherwise + // pull the whole app in here and reintroduce the same conflict this file exists to avoid. + "extends": "../tsconfig.json", "compilerOptions": { - "module": "node16", - "moduleResolution": "node16", - "target": "ES2023", - "rootDir": "..", - "types": ["node"], - "strict": true, - "paths": { - "@assets/*": ["../assets/*"], - "@components/*": ["../src/components/*"], - "@github/*": ["../.github/*"], - "@hooks/*": ["../src/hooks/*"], - "@libs/*": ["../src/libs/*"], - "@navigation/*": ["../src/libs/Navigation/*"], - "@pages/*": ["../src/pages/*"], - "@prompts/*": ["../prompts/*"], - "@scripts/*": ["../scripts/*", "../.github/scripts/*"], - "@styles/*": ["../src/styles/*"], - "@src/*": ["../src/*"], - "@userActions/*": ["../src/libs/actions/*"] - } - } + "types": ["@types/bun"], + "noEmit": true + }, + "include": [], + "files": ["lint.ts"] } diff --git a/tsconfig.json b/tsconfig.json index 59575a3578f3..49d0d246682e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -48,7 +48,8 @@ "**/*.nitro/*.ts", "**/*.nitro/*.tsx" ], - // CIGitLogic uses Bun's `$` shell, so it needs @types/bun, whose globals conflict with this project's. - // It is type-checked by tests/tooling/tsconfig.json instead — see the comment there. - "exclude": ["**/node_modules/*", "**/dist/*", ".github/actions/**/index.js", "**/docs/*", ".claude/worktrees/**", "tests/tooling/CIGitLogic.test.ts"] + // CIGitLogic and lint.ts use Bun's `$` shell, so they need @types/bun, whose globals conflict with this + // project's. They are type-checked by tests/tooling/tsconfig.json and scripts/tsconfig.json instead — + // see the comments there. + "exclude": ["**/node_modules/*", "**/dist/*", ".github/actions/**/index.js", "**/docs/*", ".claude/worktrees/**", "tests/tooling/CIGitLogic.test.ts", "scripts/lint.ts"] }