[WEB-5459] feat(codemods): add function declaration transformer with tests (#8137)

- Add jscodeshift-based codemod to convert arrow function components to function declarations
- Support React.FC, observer-wrapped, and forwardRef components
- Include comprehensive test suite covering edge cases
- Add npm script to run transformer across codebase
- Target only .tsx files in source directories, excluding node_modules and declaration files

* [WEB-5459] chore: updates after running codemod

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
Aaron 2025-11-20 19:09:40 +07:00 committed by GitHub
parent 90866fb925
commit 83fdebf64d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1771 changed files with 17003 additions and 13856 deletions

View file

@ -10,7 +10,7 @@ type Props = {
selectionHelpers: TSelectionHelper;
};
export const IssueBulkOperationsRoot: React.FC<Props> = observer((props) => {
export const IssueBulkOperationsRoot = observer(function IssueBulkOperationsRoot(props: Props) {
const { className, selectionHelpers } = props;
// store hooks
const { isSelectionActive } = useMultipleSelectStore();

View file

@ -8,4 +8,6 @@ type Props = {
editable: boolean | undefined;
};
export const AppliedIssueTypeFilters: React.FC<Props> = observer(() => null);
export const AppliedIssueTypeFilters = observer(function AppliedIssueTypeFilters(_props: Props) {
return null;
});

View file

@ -9,4 +9,6 @@ type Props = {
searchQuery: string;
};
export const FilterIssueTypes: React.FC<Props> = observer(() => null);
export const FilterIssueTypes = observer(function FilterIssueTypes(_props: Props) {
return null;
});

View file

@ -9,4 +9,6 @@ type Props = {
searchQuery: string;
};
export const FilterTeamProjects: React.FC<Props> = observer(() => null);
export const FilterTeamProjects = observer(function FilterTeamProjects(_props: Props) {
return null;
});

View file

@ -33,7 +33,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
// plane web
import { CommonProjectBreadcrumbs } from "../breadcrumbs/common";
export const IssuesHeader = observer(() => {
export const IssuesHeader = observer(function IssuesHeader() {
// router
const router = useAppRouter();
const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string };

View file

@ -11,4 +11,6 @@ export type TWorkItemAdditionalWidgetActionButtonsProps = {
workspaceSlug: string;
};
export const WorkItemAdditionalWidgetActionButtons: FC<TWorkItemAdditionalWidgetActionButtonsProps> = () => null;
export function WorkItemAdditionalWidgetActionButtons(_props: TWorkItemAdditionalWidgetActionButtonsProps) {
return null;
}

View file

@ -11,4 +11,6 @@ export type TWorkItemAdditionalWidgetCollapsiblesProps = {
workspaceSlug: string;
};
export const WorkItemAdditionalWidgetCollapsibles: FC<TWorkItemAdditionalWidgetCollapsiblesProps> = () => null;
export function WorkItemAdditionalWidgetCollapsibles(_props: TWorkItemAdditionalWidgetCollapsiblesProps) {
return null;
}

View file

@ -10,4 +10,6 @@ export type TWorkItemAdditionalWidgetModalsProps = {
workspaceSlug: string;
};
export const WorkItemAdditionalWidgetModals: FC<TWorkItemAdditionalWidgetModalsProps> = () => null;
export function WorkItemAdditionalWidgetModals(_props: TWorkItemAdditionalWidgetModalsProps) {
return null;
}

View file

@ -10,4 +10,6 @@ export type TAdditionalActivityRoot = {
field: string | undefined;
};
export const AdditionalActivityRoot: FC<TAdditionalActivityRoot> = observer(() => <></>);
export const AdditionalActivityRoot = observer(function AdditionalActivityRoot(_props: TAdditionalActivityRoot) {
return <></>;
});

View file

@ -11,4 +11,6 @@ export type TWorkItemAdditionalSidebarProperties = {
isPeekView?: boolean;
};
export const WorkItemAdditionalSidebarProperties: FC<TWorkItemAdditionalSidebarProperties> = () => <></>;
export function WorkItemAdditionalSidebarProperties(_props: TWorkItemAdditionalSidebarProperties) {
return <></>;
}

View file

@ -8,7 +8,7 @@ type TIssueUser = {
customUserName?: string;
};
export const IssueCreatorDisplay: FC<TIssueUser> = (props) => {
export function IssueCreatorDisplay(props: TIssueUser) {
const { activityId, customUserName } = props;
// hooks
const {
@ -33,4 +33,4 @@ export const IssueCreatorDisplay: FC<TIssueUser> = (props) => {
)}
</>
);
};
}

View file

@ -36,7 +36,9 @@ type TIssueTypeIdentifier = {
size?: "xs" | "sm" | "md" | "lg";
};
export const IssueTypeIdentifier: FC<TIssueTypeIdentifier> = observer((_props) => <></>);
export const IssueTypeIdentifier = observer(function IssueTypeIdentifier(_props: TIssueTypeIdentifier) {
return <></>;
});
type TIdentifierTextProps = {
identifier: string;
@ -44,7 +46,7 @@ type TIdentifierTextProps = {
textContainerClassName?: string;
};
export const IdentifierText: React.FC<TIdentifierTextProps> = (props) => {
export function IdentifierText(props: TIdentifierTextProps) {
const { identifier, enableClickToCopyIdentifier = false, textContainerClassName } = props;
// handlers
const handleCopyIssueIdentifier = () => {
@ -74,9 +76,9 @@ export const IdentifierText: React.FC<TIdentifierTextProps> = (props) => {
</span>
</Tooltip>
);
};
}
export const IssueIdentifier: React.FC<TIssueIdentifierProps> = observer((props) => {
export const IssueIdentifier = observer(function IssueIdentifier(props: TIssueIdentifierProps) {
const { projectId, textContainerClassName, displayProperties, enableClickToCopyIdentifier = false } = props;
// store hooks
const { getProjectIdentifierById } = useProject();

View file

@ -5,4 +5,6 @@ type TIssueAdditionalPropertiesActivity = {
ends: "top" | "bottom" | undefined;
};
export const IssueAdditionalPropertiesActivity: FC<TIssueAdditionalPropertiesActivity> = () => <></>;
export function IssueAdditionalPropertiesActivity(_props: TIssueAdditionalPropertiesActivity) {
return <></>;
}

View file

@ -5,4 +5,6 @@ import { observer } from "mobx-react";
export type TIssueTypeActivity = { activityId: string; showIssue?: boolean; ends: "top" | "bottom" | undefined };
export const IssueTypeActivity: FC<TIssueTypeActivity> = observer(() => <></>);
export const IssueTypeActivity = observer(function IssueTypeActivity(_props: TIssueTypeActivity) {
return <></>;
});

View file

@ -9,7 +9,7 @@ export type TIssueTypeSwitcherProps = {
disabled: boolean;
};
export const IssueTypeSwitcher: React.FC<TIssueTypeSwitcherProps> = observer((props) => {
export const IssueTypeSwitcher = observer(function IssueTypeSwitcher(props: TIssueTypeSwitcherProps) {
const { issueId } = props;
// store hooks
const {

View file

@ -20,7 +20,7 @@ type TIssueParentSelect = {
workspaceSlug: string;
};
export const IssueParentSelectRoot: React.FC<TIssueParentSelect> = observer((props) => {
export const IssueParentSelectRoot = observer(function IssueParentSelectRoot(props: TIssueParentSelect) {
const { issueId, issueOperations, projectId, workspaceSlug } = props;
const { t } = useTranslation();
// store hooks

View file

@ -6,4 +6,6 @@ export type TDateAlertProps = {
projectId: string;
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const DateAlert = (props: TDateAlertProps) => <></>;
export function DateAlert(props: TDateAlertProps) {
return <></>;
}

View file

@ -1,3 +1,5 @@
import type { TIssue } from "@plane/types";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const TransferHopInfo = ({ workItem }: { workItem: TIssue }) => <></>;
export function TransferHopInfo({ workItem }: { workItem: TIssue }) {
return <></>;
}

View file

@ -7,4 +7,6 @@ export type TWorkItemLayoutAdditionalProperties = {
issue: TIssue;
};
export const WorkItemLayoutAdditionalProperties: FC<TWorkItemLayoutAdditionalProperties> = (props) => <></>;
export function WorkItemLayoutAdditionalProperties(props: TWorkItemLayoutAdditionalProperties) {
return <></>;
}

View file

@ -1,3 +1,5 @@
import { observer } from "mobx-react";
export const TeamEmptyState: React.FC = observer(() => <></>);
export const TeamEmptyState = observer(function TeamEmptyState() {
return <></>;
});

View file

@ -1,3 +1,5 @@
import { observer } from "mobx-react";
export const TeamProjectWorkItemEmptyState: React.FC = observer(() => <></>);
export const TeamProjectWorkItemEmptyState = observer(function TeamProjectWorkItemEmptyState() {
return <></>;
});

View file

@ -1,3 +1,5 @@
import { observer } from "mobx-react";
export const TeamViewEmptyState: React.FC = observer(() => <></>);
export const TeamViewEmptyState = observer(function TeamViewEmptyState() {
return <></>;
});

View file

@ -11,4 +11,6 @@ type Props = {
showLabel?: boolean;
};
export const IssueStats: FC<Props> = (props) => <></>;
export function IssueStats(props: Props) {
return <></>;
}

View file

@ -8,4 +8,6 @@ type TDuplicateWorkItemModalProps = {
projectId: string;
};
export const DuplicateWorkItemModal: FC<TDuplicateWorkItemModalProps> = () => <></>;
export function DuplicateWorkItemModal(_props: TDuplicateWorkItemModalProps) {
return <></>;
}

View file

@ -23,4 +23,6 @@ export type TIssueTypeSelectProps<T extends Partial<TIssueFields>> = {
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const IssueTypeSelect = <T extends Partial<TIssueFields>>(props: TIssueTypeSelectProps<T>) => <></>;
export function IssueTypeSelect<T extends Partial<TIssueFields>>(props: TIssueTypeSelectProps<T>) {
return <></>;
}

View file

@ -7,4 +7,6 @@ export type TWorkItemModalAdditionalPropertiesProps = {
workspaceSlug: string;
};
export const WorkItemModalAdditionalProperties: React.FC<TWorkItemModalAdditionalPropertiesProps> = () => null;
export function WorkItemModalAdditionalProperties(_props: TWorkItemModalAdditionalPropertiesProps) {
return null;
}

View file

@ -14,7 +14,7 @@ export type TIssueModalProviderProps = {
children: React.ReactNode;
};
export const IssueModalProvider = observer((props: TIssueModalProviderProps) => {
export const IssueModalProvider = observer(function IssueModalProvider(props: TIssueModalProviderProps) {
const { children, allowedProjectIds } = props;
// states
const [selectedParentIssue, setSelectedParentIssue] = useState<ISearchIssueResponse | null>(null);

View file

@ -13,4 +13,6 @@ export type TWorkItemTemplateSelect = {
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const WorkItemTemplateSelect = (props: TWorkItemTemplateSelect) => <></>;
export function WorkItemTemplateSelect(props: TWorkItemTemplateSelect) {
return <></>;
}

View file

@ -34,7 +34,7 @@ export type TQuickAddIssueFormRoot = {
isEpic: boolean;
};
export const QuickAddIssueFormRoot: FC<TQuickAddIssueFormRoot> = observer((props) => {
export const QuickAddIssueFormRoot = observer(function QuickAddIssueFormRoot(props: TQuickAddIssueFormRoot) {
const { isOpen, layout, projectId, hasError = false, setFocus, register, onSubmit, onClose, isEpic } = props;
// store hooks
const { getProjectById } = useProject();

View file

@ -14,7 +14,7 @@ export type TActivityFilterRoot = {
isIntakeIssue?: boolean;
};
export const ActivityFilterRoot: FC<TActivityFilterRoot> = (props) => {
export function ActivityFilterRoot(props: TActivityFilterRoot) {
const { selectedFilters, toggleFilter } = props;
const filters: TActivityFilterOption[] = Object.entries(ACTIVITY_FILTER_TYPE_OPTIONS).map(([key, value]) => {
@ -28,4 +28,4 @@ export const ActivityFilterRoot: FC<TActivityFilterRoot> = (props) => {
});
return <ActivityFilter selectedFilters={selectedFilters} filterOptions={filters} />;
};
}

View file

@ -11,4 +11,6 @@ type TIssueActivityWorklog = {
ends?: "top" | "bottom";
};
export const IssueActivityWorklog: FC<TIssueActivityWorklog> = () => <></>;
export function IssueActivityWorklog(_props: TIssueActivityWorklog) {
return <></>;
}

View file

@ -9,4 +9,6 @@ type TIssueActivityWorklogCreateButton = {
disabled: boolean;
};
export const IssueActivityWorklogCreateButton: FC<TIssueActivityWorklogCreateButton> = () => <></>;
export function IssueActivityWorklogCreateButton(_props: TIssueActivityWorklogCreateButton) {
return <></>;
}

View file

@ -9,4 +9,6 @@ type TIssueWorklogProperty = {
disabled: boolean;
};
export const IssueWorklogProperty: FC<TIssueWorklogProperty> = () => <></>;
export function IssueWorklogProperty(_props: TIssueWorklogProperty) {
return <></>;
}