Dev X: Destructure props in functional component's argument (#2582)

This commit is contained in:
RachelElysia 2021-10-22 11:34:45 -04:00 committed by GitHub
parent 70dc68f329
commit 403ef5cc59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 195 additions and 204 deletions

View File

@ -23,11 +23,9 @@ const { HOME } = paths;
/** /**
* Checks if a user is a global admin or global maintainer when routing * Checks if a user is a global admin or global maintainer when routing
*/ */
const AuthAnyMaintainerGlobalAdminRoutes = ( const AuthAnyMaintainerGlobalAdminRoutes = ({
props: IAuthAnyMaintainerGlobalAdminRoutesProps children,
): JSX.Element | null => { }: IAuthAnyMaintainerGlobalAdminRoutesProps): JSX.Element | null => {
const { children } = props;
const dispatch = useDispatch(); const dispatch = useDispatch();
const user = useSelector((state: IRootState) => state.auth.user); const user = useSelector((state: IRootState) => state.auth.user);

View File

@ -23,11 +23,9 @@ const { HOME } = paths;
/** /**
* Checks if a user is a global admin or global maintainer when routing * Checks if a user is a global admin or global maintainer when routing
*/ */
const AuthGlobalAdminMaintainerRoutes = ( const AuthGlobalAdminMaintainerRoutes = ({
props: IAuthGlobalAdminMaintainerRoutesProps children,
) => { }: IAuthGlobalAdminMaintainerRoutesProps) => {
const { children } = props;
const dispatch = useDispatch(); const dispatch = useDispatch();
const user = useSelector((state: IRootState) => state.auth.user); const user = useSelector((state: IRootState) => state.auth.user);

View File

@ -8,8 +8,11 @@ interface IIconToolTipProps {
} }
// TODO: handle html text better. possibly use 'children' prop for html // TODO: handle html text better. possibly use 'children' prop for html
const IconToolTip = (props: IIconToolTipProps): JSX.Element => { const IconToolTip = ({
const { text, isHtml, issue } = props; text,
isHtml,
issue,
}: IIconToolTipProps): JSX.Element => {
let svgIcon = ( let svgIcon = (
<svg <svg
width="16" width="16"

View File

@ -8,8 +8,7 @@ interface IInfoBannerProps {
className?: string; className?: string;
} }
const InfoBanner = (props: IInfoBannerProps): JSX.Element => { const InfoBanner = ({ children, className }: IInfoBannerProps): JSX.Element => {
const { children, className } = props;
const wrapperClasses = classNames(baseClass, className); const wrapperClasses = classNames(baseClass, className);
return <div className={wrapperClasses}>{children}</div>; return <div className={wrapperClasses}>{children}</div>;

View File

@ -18,9 +18,9 @@ interface IRootState {
const { FLEET_403 } = paths; const { FLEET_403 } = paths;
const PremiumTierRoutes = (props: IPremiumTierRoutes): JSX.Element | null => { const PremiumTierRoutes = ({
const { children } = props; children,
}: IPremiumTierRoutes): JSX.Element | null => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const config = useSelector((state: IRootState) => state.app.config); const config = useSelector((state: IRootState) => state.app.config);

View File

@ -14,8 +14,11 @@ interface IDropdownCellProps {
onChange: (value: any) => void; onChange: (value: any) => void;
} }
const DropdownCell = (props: IDropdownCellProps): JSX.Element => { const DropdownCell = ({
const { options, onChange, placeholder } = props; options,
onChange,
placeholder,
}: IDropdownCellProps): JSX.Element => {
return ( return (
<div className={baseClass}> <div className={baseClass}>
<Dropdown <Dropdown

View File

@ -5,9 +5,7 @@ interface IHeaderCellProps {
isSortedDesc?: boolean; isSortedDesc?: boolean;
} }
const HeaderCell = (props: IHeaderCellProps): JSX.Element => { const HeaderCell = ({ value, isSortedDesc }: IHeaderCellProps): JSX.Element => {
const { value, isSortedDesc } = props;
let sortArrowClass = ""; let sortArrowClass = "";
if (isSortedDesc === undefined) { if (isSortedDesc === undefined) {
sortArrowClass = ""; sortArrowClass = "";

View File

@ -7,11 +7,9 @@ interface IIconTooltipCellProps<T> {
value: string; value: string;
} }
const IconTooltipCell = ( const IconTooltipCell = ({
props: IIconTooltipCellProps<any> value,
): JSX.Element | null => { }: IIconTooltipCellProps<any>): JSX.Element | null => {
const { value } = props;
// The value passed in must be a valid FleetIcon name // The value passed in must be a valid FleetIcon name
return <FleetIcon name={value} />; return <FleetIcon name={value} />;
}; };

View File

@ -7,11 +7,9 @@ interface IIconTooltipCellProps<T> {
value: string; value: string;
} }
const IconTooltipCell = ( const IconTooltipCell = ({
props: IIconTooltipCellProps<any> value,
): JSX.Element | null => { }: IIconTooltipCellProps<any>): JSX.Element | null => {
const { value } = props;
if (isEmpty(value)) { if (isEmpty(value)) {
return null; return null;
} }

View File

@ -10,9 +10,7 @@ interface ILinkCellProps<T> {
title?: string; title?: string;
} }
const LinkCell = (props: ILinkCellProps<any>): JSX.Element => { const LinkCell = ({ value, path, title }: ILinkCellProps<any>): JSX.Element => {
const { value, path, title } = props;
const dispatch = useDispatch(); const dispatch = useDispatch();
const onClick = (): void => { const onClick = (): void => {

View File

@ -12,8 +12,7 @@ const generateClassTag = (rawValue: string): string => {
return rawValue.replace(" ", "-").toLowerCase(); return rawValue.replace(" ", "-").toLowerCase();
}; };
const PillCell = (props: IPillCellProps): JSX.Element => { const PillCell = ({ value, customIdPrefix }: IPillCellProps): JSX.Element => {
const { value, customIdPrefix } = props;
const [pillText, id] = value; const [pillText, id] = value;
const pillClassName = classnames( const pillClassName = classnames(

View File

@ -9,9 +9,7 @@ const generateClassTag = (rawValue: string): string => {
return rawValue.replace(" ", "-").toLowerCase(); return rawValue.replace(" ", "-").toLowerCase();
}; };
const StatusCell = (props: IStatusCellProps): JSX.Element => { const StatusCell = ({ value }: IStatusCellProps): JSX.Element => {
const { value } = props;
const statusClassName = classnames( const statusClassName = classnames(
"data-table__status", "data-table__status",
`data-table__status--${generateClassTag(value)}` `data-table__status--${generateClassTag(value)}`

View File

@ -6,13 +6,11 @@ interface ITextCellProps {
greyed?: string; greyed?: string;
} }
const TextCell = (props: ITextCellProps): JSX.Element => { const TextCell = ({
const { value,
value, formatter = (val) => val, // identity function if no formatter is provided
formatter = (val) => val, // identity function if no formatter is provided greyed,
greyed, }: ITextCellProps): JSX.Element => {
} = props;
let val = value; let val = value;
if (typeof value === "boolean") { if (typeof value === "boolean") {

View File

@ -14,17 +14,16 @@ interface IRadioProps {
disabled?: boolean; disabled?: boolean;
} }
const Radio = (props: IRadioProps): JSX.Element => { const Radio = ({
const { className,
className, id,
id, name,
name, value,
value, checked,
checked, disabled,
disabled, label,
label, onChange,
onChange, }: IRadioProps): JSX.Element => {
} = props;
const wrapperClasses = classnames(baseClass, className); const wrapperClasses = classnames(baseClass, className);
const radioControlClass = classnames({ const radioControlClass = classnames({

View File

@ -7,7 +7,7 @@ import FormField from "components/forms/FormField";
const Slider = (props) => { const Slider = (props) => {
const { onChange, value, inactiveText = "Off", activeText = "On" } = props; const { onChange, value, inactiveText = "Off", activeText = "On" } = props;
const baseClass = "kolide-slider"; const baseClass = "fleet-slider";
const sliderBtnClass = classnames(baseClass, { const sliderBtnClass = classnames(baseClass, {
[`${baseClass}--active`]: value, [`${baseClass}--active`]: value,

View File

@ -1,4 +1,4 @@
.kolide-slider { .fleet-slider {
transition: background-color 150ms ease-in-out; transition: background-color 150ms ease-in-out;
background-color: $core-fleet-black; background-color: $core-fleet-black;
border-radius: 12px; border-radius: 12px;

View File

@ -1,10 +1,10 @@
import React from "react"; import React from "react";
const PoliciesPageWrapper = (props: { const PoliciesPageWrapper = ({
children,
}: {
children: React.ReactNode; children: React.ReactNode;
}): React.ReactNode | null => { }): React.ReactNode | null => {
const { children } = props;
return children || null; return children || null;
}; };

View File

@ -25,15 +25,13 @@ interface IHostSidePanelProps {
canAddNewLabel: boolean; canAddNewLabel: boolean;
} }
const HostSidePanel = (props: IHostSidePanelProps): JSX.Element => { const HostSidePanel = ({
const { labels,
labels, onAddLabelClick,
onAddLabelClick, onLabelClick,
onLabelClick, selectedFilter,
selectedFilter, canAddNewLabel,
canAddNewLabel, }: IHostSidePanelProps): JSX.Element => {
} = props;
const [labelFilter, setLabelFilter] = useState<string>(""); const [labelFilter, setLabelFilter] = useState<string>("");
const onFilterLabels = useCallback( const onFilterLabels = useCallback(

View File

@ -38,8 +38,11 @@ interface IPanelGroupItemProps {
isSelected: boolean; isSelected: boolean;
} }
const PanelGroupItem = (props: IPanelGroupItemProps): JSX.Element => { const PanelGroupItem = ({
const { item, onLabelClick, isSelected } = props; item,
onLabelClick,
isSelected,
}: IPanelGroupItemProps): JSX.Element => {
const { const {
count, count,
display_text: displayText, display_text: displayText,

View File

@ -45,12 +45,10 @@ const getTabIndex = (path: string): number => {
const baseClass = "settings-wrapper"; const baseClass = "settings-wrapper";
const SettingsWrapper = (props: ISettingsWrapperProp): JSX.Element => { const SettingsWrapper = ({
const { children,
children, location: { pathname },
location: { pathname }, }: ISettingsWrapperProp): JSX.Element => {
} = props;
// Add Teams tab for premium tier only // Add Teams tab for premium tier only
const config = useSelector((state: IRootState) => state.app.config); const config = useSelector((state: IRootState) => state.app.config);

View File

@ -32,10 +32,9 @@ interface IRootState {
}; };
} }
const AgentOptionsPage = (props: IAgentOptionsPageProps): JSX.Element => { const AgentOptionsPage = ({
const { params: { team_id },
params: { team_id }, }: IAgentOptionsPageProps): JSX.Element => {
} = props;
const teamId = parseInt(team_id, 10); const teamId = parseInt(team_id, 10);
const dispatch = useDispatch(); const dispatch = useDispatch();
const team = useSelector((state: IRootState) => { const team = useSelector((state: IRootState) => {

View File

@ -72,10 +72,9 @@ const memoizedGetTeams = memoize(getTeams);
// with the same table query params after we have made an edit to a user. // with the same table query params after we have made an edit to a user.
let tableQueryData = {}; let tableQueryData = {};
const MembersPage = (props: IMembersPageProps): JSX.Element => { const MembersPage = ({
const { params: { team_id },
params: { team_id }, }: IMembersPageProps): JSX.Element => {
} = props;
const teamId = parseInt(team_id, 10); const teamId = parseInt(team_id, 10);
const dispatch = useDispatch(); const dispatch = useDispatch();

View File

@ -16,9 +16,12 @@ interface IAddMemberModal {
onSubmit: (userIds: INewMembersBody) => void; onSubmit: (userIds: INewMembersBody) => void;
} }
const AddMemberModal = (props: IAddMemberModal): JSX.Element => { const AddMemberModal = ({
const { disabledMembers, onCancel, onSubmit, team } = props; disabledMembers,
onCancel,
onSubmit,
team,
}: IAddMemberModal): JSX.Element => {
const [selectedMembers, setSelectedMembers] = useState([]); const [selectedMembers, setSelectedMembers] = useState([]);
const onChangeDropdown = useCallback( const onChangeDropdown = useCallback(

View File

@ -56,21 +56,17 @@ const generateOptionLabel = (user: IUser, team: ITeam): string => {
return user.name; return user.name;
}; };
const AutocompleteDropdown = ( const AutocompleteDropdown = ({
props: IAutocompleteDropdownProps className,
): JSX.Element => { disabled,
const { disabledOptions,
className, placeholder,
disabled, onChange,
disabledOptions, id,
placeholder, resourceUrl,
onChange, value,
id, team,
resourceUrl, }: IAutocompleteDropdownProps): JSX.Element => {
value,
team,
} = props;
const wrapperClass = classnames(baseClass, className); const wrapperClass = classnames(baseClass, className);
// We disable any filtering client side as the server filters the results // We disable any filtering client side as the server filters the results

View File

@ -12,9 +12,12 @@ interface IDeleteTeamModalProps {
onCancel: () => void; onCancel: () => void;
} }
const RemoveMemberModal = (props: IDeleteTeamModalProps): JSX.Element => { const RemoveMemberModal = ({
const { memberName, teamName, onSubmit, onCancel } = props; memberName,
teamName,
onSubmit,
onCancel,
}: IDeleteTeamModalProps): JSX.Element => {
return ( return (
<Modal title={"Delete team"} onExit={onCancel} className={baseClass}> <Modal title={"Delete team"} onExit={onCancel} className={baseClass}>
<form className={`${baseClass}__form`}> <form className={`${baseClass}__form`}>

View File

@ -77,13 +77,11 @@ const getTabIndex = (path: string, teamId: number): number => {
}); });
}; };
const TeamDetailsWrapper = (props: ITeamDetailsPageProps): JSX.Element => { const TeamDetailsWrapper = ({
const { children,
children, location: { pathname },
location: { pathname }, params: { team_id },
params: { team_id }, }: ITeamDetailsPageProps): JSX.Element => {
} = props;
const isLoadingTeams = useSelector( const isLoadingTeams = useSelector(
(state: IRootState) => state.entities.teams.loading (state: IRootState) => state.entities.teams.loading
); );

View File

@ -9,9 +9,10 @@ interface IAddHostsModalProps {
const baseClass = "add-hosts-redirect-modal"; const baseClass = "add-hosts-redirect-modal";
const AddHostsRedirectModal = (props: IAddHostsModalProps): JSX.Element => { const AddHostsRedirectModal = ({
const { onCancel, onSubmit } = props; onCancel,
onSubmit,
}: IAddHostsModalProps): JSX.Element => {
return ( return (
<Modal title={"Add hosts"} onExit={onCancel} className={baseClass}> <Modal title={"Add hosts"} onExit={onCancel} className={baseClass}>
<div className={`${baseClass}__modal-body`}> <div className={`${baseClass}__modal-body`}>

View File

@ -17,9 +17,10 @@ interface ICreateTeamModalProps {
onSubmit: (formData: ICreateTeamFormData) => void; onSubmit: (formData: ICreateTeamFormData) => void;
} }
const CreateTeamModal = (props: ICreateTeamModalProps): JSX.Element => { const CreateTeamModal = ({
const { onCancel, onSubmit } = props; onCancel,
onSubmit,
}: ICreateTeamModalProps): JSX.Element => {
const [name, setName] = useState(""); const [name, setName] = useState("");
const onInputChange = useCallback( const onInputChange = useCallback(

View File

@ -11,9 +11,11 @@ interface IDeleteTeamModalProps {
onCancel: () => void; onCancel: () => void;
} }
const DeleteTeamModal = (props: IDeleteTeamModalProps): JSX.Element => { const DeleteTeamModal = ({
const { name, onSubmit, onCancel } = props; name,
onSubmit,
onCancel,
}: IDeleteTeamModalProps): JSX.Element => {
return ( return (
<Modal title={"Delete team"} onExit={onCancel} className={baseClass}> <Modal title={"Delete team"} onExit={onCancel} className={baseClass}>
<form className={`${baseClass}__form`}> <form className={`${baseClass}__form`}>

View File

@ -17,9 +17,11 @@ interface IEditTeamModalProps {
defaultName: string; defaultName: string;
} }
const EditTeamModal = (props: IEditTeamModalProps): JSX.Element => { const EditTeamModal = ({
const { onCancel, onSubmit, defaultName } = props; onCancel,
onSubmit,
defaultName,
}: IEditTeamModalProps): JSX.Element => {
const [name, setName] = useState(defaultName); const [name, setName] = useState(defaultName);
const onInputChange = useCallback( const onInputChange = useCallback(

View File

@ -9,9 +9,11 @@ interface IDeleteUserForm {
onCancel: () => void; onCancel: () => void;
} }
const DeleteUserForm = (props: IDeleteUserForm): JSX.Element => { const DeleteUserForm = ({
const { name, onDelete, onCancel } = props; name,
onDelete,
onCancel,
}: IDeleteUserForm): JSX.Element => {
return ( return (
<div className={baseClass}> <div className={baseClass}>
<p> <p>

View File

@ -21,21 +21,19 @@ interface IEditUserModalProps {
const baseClass = "edit-user-modal"; const baseClass = "edit-user-modal";
const EditUserModal = (props: IEditUserModalProps): JSX.Element => { const EditUserModal = ({
const { onCancel,
onCancel, onSubmit,
onSubmit, defaultName,
defaultName, defaultEmail,
defaultEmail, defaultGlobalRole,
defaultGlobalRole, defaultTeams,
defaultTeams, availableTeams,
availableTeams, isPremiumTier,
isPremiumTier, smtpConfigured,
smtpConfigured, canUseSso,
canUseSso, isSsoEnabled,
isSsoEnabled, }: IEditUserModalProps): JSX.Element => {
} = props;
return ( return (
<Modal <Modal
title="Edit user" title="Edit user"

View File

@ -119,8 +119,11 @@ const useSelectedTeamState = (
return [teamsFormList, updateSelectedTeams] as const; return [teamsFormList, updateSelectedTeams] as const;
}; };
const SelectedTeamsForm = (props: ISelectedTeamsFormProps): JSX.Element => { const SelectedTeamsForm = ({
const { availableTeams, usersCurrentTeams, onFormChange } = props; availableTeams,
usersCurrentTeams,
onFormChange,
}: ISelectedTeamsFormProps): JSX.Element => {
const [teamsFormList, updateSelectedTeams] = useSelectedTeamState( const [teamsFormList, updateSelectedTeams] = useSelectedTeamState(
availableTeams, availableTeams,
usersCurrentTeams, usersCurrentTeams,

View File

@ -122,8 +122,6 @@ class UserForm extends Component<ICreateUserFormProps, ICreateUserFormState> {
}, },
isGlobalUser: props.defaultGlobalRole !== null, isGlobalUser: props.defaultGlobalRole !== null,
}; };
const { isPremiumTier } = props;
} }
onInputChange = (formField: string): ((value: string) => void) => { onInputChange = (formField: string): ((value: string) => void) => {

View File

@ -35,16 +35,14 @@ const onQueryHostSaved = (host, selectedQuery, dispatch) => {
); );
}; };
const SelectQueryModal = (props) => { const SelectQueryModal = ({
const { host,
host, onCancel,
onCancel, dispatch,
dispatch, queries,
queries, queryErrors,
queryErrors, isOnlyObserver,
isOnlyObserver, }) => {
} = props;
let queriesAvailableToRun = queries; let queriesAvailableToRun = queries;
if (isOnlyObserver) { if (isOnlyObserver) {

View File

@ -45,9 +45,12 @@ const getHiddenColumns = (columns) => {
.map((column) => column.accessor); .map((column) => column.accessor);
}; };
const EditColumnsModal = (props) => { const EditColumnsModal = ({
const { columns, hiddenColumns, onSaveColumns, onCancelColumns } = props; columns,
hiddenColumns,
onSaveColumns,
onCancelColumns,
}) => {
const [columnItems, updateColumnItems] = useCheckboxListStateManagement( const [columnItems, updateColumnItems] = useCheckboxListStateManagement(
columns, columns,
hiddenColumns hiddenColumns

View File

@ -13,10 +13,12 @@ interface IRemovePackQueryModalProps {
selectedQueryIds: number[]; selectedQueryIds: number[];
} }
const RemovePackQueryModal = ( const RemovePackQueryModal = ({
props: IRemovePackQueryModalProps onCancel,
): JSX.Element => { onSubmit,
const { onCancel, onSubmit, selectedQuery, selectedQueryIds } = props; selectedQuery,
selectedQueryIds,
}: IRemovePackQueryModalProps): JSX.Element => {
const queryOrQueries = const queryOrQueries =
selectedQuery || selectedQueryIds?.length === 1 ? "query" : "queries"; selectedQuery || selectedQueryIds?.length === 1 ? "query" : "queries";
return ( return (

View File

@ -20,18 +20,16 @@ interface IPoliciesListWrapperProps {
tableType?: string; tableType?: string;
} }
const PoliciesListWrapper = (props: IPoliciesListWrapperProps): JSX.Element => { const PoliciesListWrapper = ({
const { policiesList,
policiesList, isLoading,
isLoading, onRemovePoliciesClick,
onRemovePoliciesClick, toggleAddPolicyModal,
toggleAddPolicyModal, resultsTitle,
resultsTitle, selectedTeamId,
selectedTeamId, canAddOrRemovePolicy,
canAddOrRemovePolicy, tableType,
tableType, }: IPoliciesListWrapperProps): JSX.Element => {
} = props;
const NoPolicies = () => { const NoPolicies = () => {
return ( return (
<div className={`${noPoliciesClass}`}> <div className={`${noPoliciesClass}`}>

View File

@ -10,9 +10,10 @@ interface IRemovePoliciesModalProps {
onSubmit: () => void; onSubmit: () => void;
} }
const RemovePoliciesModal = (props: IRemovePoliciesModalProps): JSX.Element => { const RemovePoliciesModal = ({
const { onCancel, onSubmit } = props; onCancel,
onSubmit,
}: IRemovePoliciesModalProps): JSX.Element => {
return ( return (
<Modal title={"Remove policies"} onExit={onCancel} className={baseClass}> <Modal title={"Remove policies"} onExit={onCancel} className={baseClass}>
<div className={baseClass}> <div className={baseClass}>

View File

@ -10,9 +10,10 @@ interface IRemoveQueryModalProps {
onSubmit: () => void; onSubmit: () => void;
} }
const RemoveQueryModal = (props: IRemoveQueryModalProps): JSX.Element => { const RemoveQueryModal = ({
const { onCancel, onSubmit } = props; onCancel,
onSubmit,
}: IRemoveQueryModalProps): JSX.Element => {
return ( return (
<Modal title={"Delete query"} onExit={onCancel} className={baseClass}> <Modal title={"Delete query"} onExit={onCancel} className={baseClass}>
<div className={baseClass}> <div className={baseClass}>

View File

@ -135,10 +135,9 @@ interface ITeamOptions {
value: string | number; value: string | number;
} }
const ManageSchedulePage = (props: ITeamSchedulesPageProps): JSX.Element => { const ManageSchedulePage = ({
const { params: { team_id },
params: { team_id }, }: ITeamSchedulesPageProps): JSX.Element => {
} = props;
const teamId = parseInt(team_id, 10); const teamId = parseInt(team_id, 10);
const dispatch = useDispatch(); const dispatch = useDispatch();
const { MANAGE_PACKS } = paths; const { MANAGE_PACKS } = paths;

View File

@ -10,11 +10,10 @@ interface IRemoveScheduledQueryModalProps {
onSubmit: () => void; onSubmit: () => void;
} }
const RemoveScheduledQueryModal = ( const RemoveScheduledQueryModal = ({
props: IRemoveScheduledQueryModalProps onCancel,
): JSX.Element => { onSubmit,
const { onCancel, onSubmit } = props; }: IRemoveScheduledQueryModalProps): JSX.Element => {
return ( return (
<Modal <Modal
title={"Remove scheduled query"} title={"Remove scheduled query"}

View File

@ -48,16 +48,15 @@ interface IRootState {
}; };
} }
const ScheduleListWrapper = (props: IScheduleListWrapperProps): JSX.Element => { const ScheduleListWrapper = ({
const { onRemoveScheduledQueryClick,
onRemoveScheduledQueryClick, allScheduledQueriesList,
allScheduledQueriesList, toggleScheduleEditorModal,
toggleScheduleEditorModal, onEditScheduledQueryClick,
onEditScheduledQueryClick, teamId,
teamId, inheritedQueries,
inheritedQueries, isTeamMaintainer,
isTeamMaintainer, }: IScheduleListWrapperProps): JSX.Element => {
} = props;
const dispatch = useDispatch(); const dispatch = useDispatch();
const { MANAGE_PACKS } = paths; const { MANAGE_PACKS } = paths;