@refinedev/core
Version:
refine is a React-based framework for building internal tools, rapidly. It ships with Ant Design System, an enterprise-level UI toolkit.
1 lines • 758 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.tsx","../src/components/pages/error/index.tsx","../src/hooks/auth/usePermissions/index.ts","../src/contexts/auth/index.tsx","../src/definitions/table/index.ts","../src/definitions/helpers/userFriendlySeconds/index.ts","../src/definitions/helpers/importCSVMapper/index.ts","../src/definitions/helpers/userFriendlyResourceName/index.ts","../src/definitions/helpers/handleUseParams/index.tsx","../src/definitions/helpers/keys/index.ts","../src/definitions/helpers/pickNotDeprecated/index.ts","../src/definitions/helpers/queryKeys/index.ts","../src/definitions/helpers/hasPermission/index.ts","../src/definitions/helpers/router/is-parameter.ts","../src/definitions/helpers/router/split-to-segments.ts","../src/definitions/helpers/router/is-segment-counts-same.ts","../src/definitions/helpers/router/remove-leading-trailing-slashes.ts","../src/definitions/helpers/router/check-by-segments.ts","../src/definitions/helpers/router/get-default-action-path.ts","../src/definitions/helpers/router/get-parent-resource.ts","../src/definitions/helpers/router/get-parent-prefix-for-resource.ts","../src/definitions/helpers/router/get-action-routes-from-resource.ts","../src/definitions/helpers/router/pick-matched-route.ts","../src/definitions/helpers/router/match-resource-from-route.ts","../src/definitions/helpers/routeGenerator/index.ts","../src/definitions/helpers/treeView/createTreeView/index.ts","../src/definitions/helpers/humanizeString/index.ts","../src/contexts/refine/index.tsx","../src/components/layoutWrapper/defaultLayout/index.tsx","../src/definitions/helpers/handleRefineOptions/index.ts","../src/definitions/helpers/redirectPage/index.ts","../src/definitions/helpers/sequentialPromises/index.ts","../src/definitions/helpers/pick-resource/index.ts","../src/definitions/helpers/pickDataProvider/index.ts","../src/definitions/helpers/handleMultiple/index.ts","../src/definitions/helpers/useInfinitePagination/index.ts","../src/definitions/helpers/legacy-resource-transform/index.ts","../src/definitions/helpers/router/pick-route-params.ts","../src/definitions/helpers/router/prepare-route-params.ts","../src/definitions/helpers/router/compose-route.ts","../src/definitions/helpers/useActiveAuthProvider/index.ts","../src/definitions/helpers/handlePaginationParams/index.ts","../src/definitions/helpers/useMediaQuery/index.ts","../src/definitions/helpers/safe-translate/index.ts","../src/definitions/helpers/generateDocumentTitle/index.ts","../src/hooks/refine/useMutationMode.ts","../src/hooks/refine/useWarnAboutChange/index.ts","../src/contexts/unsavedWarn/index.tsx","../src/hooks/refine/useSyncWithLocation.ts","../src/hooks/refine/useTitle.tsx","../src/hooks/refine/useRefineContext.ts","../src/definitions/helpers/useUserFriendlyName/index.ts","../src/definitions/helpers/flatten-object-keys/index.ts","../src/definitions/helpers/property-path-to-array/index.ts","../src/definitions/helpers/downloadInBrowser/index.ts","../src/definitions/helpers/defer-execution/index.ts","../src/definitions/helpers/async-debounce/index.ts","../src/definitions/helpers/prepare-query-context/index.ts","../src/definitions/upload/file2Base64/index.ts","../src/hooks/useKeys/index.tsx","../src/hooks/auth/useGetIdentity/index.ts","../src/hooks/auth/useLogout/index.ts","../src/hooks/auth/useInvalidateAuthStore/index.ts","../src/hooks/auth/useLogin/index.ts","../src/hooks/auth/useRegister/index.ts","../src/hooks/auth/useForgotPassword/index.ts","../src/hooks/auth/useUpdatePassword/index.ts","../src/hooks/auth/useIsAuthenticated/index.ts","../src/hooks/auth/useOnError/index.ts","../src/hooks/auth/useIsExistAuthentication/index.ts","../src/hooks/data/useList.ts","../src/hooks/useLoadingOvertime/index.ts","../src/hooks/data/useOne.ts","../src/hooks/data/useMany.ts","../src/hooks/data/useUpdate.ts","../src/contexts/undoableQueue/types.ts","../src/hooks/data/useCreate.ts","../src/hooks/data/useDelete.ts","../src/hooks/data/useCreateMany.ts","../src/hooks/data/useUpdateMany.ts","../src/hooks/data/useDeleteMany.ts","../src/hooks/data/useApiUrl.ts","../src/hooks/data/useCustom.ts","../src/hooks/data/useCustomMutation.ts","../src/hooks/data/useDataProvider.tsx","../src/contexts/data/index.tsx","../src/hooks/data/useInfiniteList.ts","../src/hooks/live/useResourceSubscription/index.ts","../src/contexts/live/index.tsx","../src/hooks/invalidate/index.tsx","../src/hooks/resource/useResource/index.ts","../src/contexts/resource/index.tsx","../src/hooks/deepMemo/index.tsx","../src/hooks/memoized/index.tsx","../src/contexts/router/picker/index.tsx","../src/hooks/router/use-parsed/index.tsx","../src/contexts/router/index.tsx","../src/hooks/router/use-parse/index.tsx","../src/hooks/resource/useResourceWithRoute/index.ts","../src/hooks/live/useLiveMode/index.ts","../src/hooks/live/useSubscription/index.ts","../src/hooks/live/usePublish/index.ts","../src/hooks/notification/useCancelNotification/index.tsx","../src/contexts/undoableQueue/index.tsx","../src/hooks/notification/useNotification/index.ts","../src/contexts/notification/index.tsx","../src/hooks/notification/useHandleNotification/index.ts","../src/hooks/i18n/useSetLocale.ts","../src/contexts/i18n/index.tsx","../src/hooks/i18n/useTranslate.ts","../src/hooks/i18n/useGetLocale.ts","../src/hooks/i18n/useTranslation.tsx","../src/hooks/export/index.ts","../src/hooks/form/index.ts","../src/hooks/redirection/index.ts","../src/hooks/router/use-back/index.tsx","../src/hooks/router/use-go/index.tsx","../src/hooks/router/use-get-to-path/index.ts","../src/hooks/navigation/index.ts","../src/hooks/show/index.ts","../src/hooks/import/index.tsx","../src/hooks/modal/useModal/index.tsx","../src/hooks/router/use-to-path/index.ts","../src/components/link/index.tsx","../src/hooks/router/use-link/index.tsx","../src/hooks/legacy-router/useRouterContext.ts","../src/contexts/router/legacy/index.tsx","../src/hooks/accessControl/useCan/index.ts","../src/contexts/accessControl/index.tsx","../src/definitions/helpers/sanitize-resource/index.ts","../src/hooks/accessControl/useCanWithoutCache.ts","../src/hooks/useSelect/index.ts","../src/hooks/useTable/index.ts","../src/hooks/auditLog/useLog/index.ts","../src/contexts/auditLog/index.tsx","../src/hooks/auditLog/useLogList/index.ts","../src/hooks/breadcrumb/index.ts","../src/hooks/menu/useMenu.tsx","../src/definitions/helpers/menu/create-resource-key.ts","../src/definitions/helpers/menu/create-tree.ts","../src/contexts/metaContext/index.tsx","../src/hooks/useMeta/index.ts","../src/hooks/use-refine-options/index.tsx","../src/hooks/use-resource-params/index.ts","../src/hooks/use-resource-params/use-id/index.tsx","../src/hooks/use-resource-params/use-action/index.tsx","../src/hooks/button/actionable-button/index.tsx","../src/hooks/button/navigation-button/index.tsx","../src/hooks/button/button-can-access/index.tsx","../src/hooks/button/delete-button/index.tsx","../src/hooks/button/refresh-button/index.tsx","../src/hooks/button/index.tsx","../src/components/pages/login/index.tsx","../src/components/pages/auth/index.tsx","../src/components/pages/auth/components/login/index.tsx","../src/components/pages/auth/components/register/index.tsx","../src/components/pages/auth/components/forgotPassword/index.tsx","../src/components/pages/auth/components/updatePassword/index.tsx","../src/components/pages/ready/index.tsx","../src/components/pages/welcome/index.tsx","../src/components/pages/config-success/index.tsx","../src/components/pages/config-error/index.tsx","../src/components/containers/refine/index.tsx","../src/components/telemetry/index.tsx","../src/hooks/useTelemetryData/index.ts","../src/definitions/helpers/check-router-prop-misuse/index.ts","../src/hooks/router/use-router-misuse-warning/index.ts","../src/components/undoableQueue/index.tsx","../src/components/layoutWrapper/index.tsx","../src/components/authenticated/index.tsx","../src/components/routeChangeHandler/index.tsx","../src/components/canAccess/index.tsx","../src/components/gh-banner/index.tsx","../src/components/gh-banner/styles.ts","../src/components/autoSaveIndicator/index.tsx"],"sourcesContent":["export * from \"./components/index.js\";\nexport * from \"./hooks/index.js\";\n\n// all auth types\nexport * from \"./components/pages/auth/types.js\";\nexport { ILoginForm } from \"./components/pages/login/index.js\";\n\nexport {\n getDefaultFilter,\n getDefaultSortOrder,\n parseTableParams,\n parseTableParamsFromQuery,\n setInitialFilters,\n setInitialSorters,\n stringifyTableParams,\n unionFilters,\n unionSorters,\n} from \"./definitions/table/index.js\";\nexport {\n createTreeView,\n handleUseParams,\n importCSVMapper,\n routeGenerator,\n userFriendlyResourceName,\n getNextPageParam,\n getPreviousPageParam,\n pickNotDeprecated,\n legacyResourceTransform,\n matchResourceFromRoute,\n useActiveAuthProvider,\n useUserFriendlyName,\n queryKeys,\n pickDataProvider,\n keys,\n KeyBuilder,\n flattenObjectKeys,\n propertyPathToArray,\n} from \"./definitions/helpers/index.js\";\nexport { file2Base64 } from \"./definitions/upload/index.js\";\nexport { generateDefaultDocumentTitle } from \"./definitions/index.js\";\n\nexport { ResourceContext } from \"./contexts/resource/index.js\";\n\nexport { AccessControlContext } from \"./contexts/accessControl/index.js\";\n\nexport {\n AccessControlProvider,\n AccessControlProvider as AccessControlBindings,\n CanParams,\n CanResponse,\n CanReturnType,\n IAccessControlContext,\n IAccessControlContextReturnType,\n} from \"./contexts/accessControl/types.js\";\n\nexport {\n AuditLogProvider,\n IAuditLogContext,\n ILog,\n ILogData,\n LogParams,\n} from \"./contexts/auditLog/types.js\";\n\nexport {\n AuthActionResponse,\n AuthBindings,\n AuthProvider,\n CheckResponse,\n IAuthContext,\n IdentityResponse,\n ILegacyAuthContext,\n LegacyAuthProvider,\n OnErrorResponse,\n PermissionResponse,\n SuccessNotificationResponse,\n} from \"./contexts/auth/types.js\";\n\nexport {\n ConditionalFilter,\n CreateManyResponse,\n CreateResponse,\n CrudFilter,\n CrudFilters,\n CrudOperators,\n CrudSort,\n CrudSorting,\n CustomResponse,\n DataBindings,\n DeleteManyResponse,\n DeleteOneResponse,\n GetListResponse,\n GetManyResponse,\n GetOneResponse,\n LogicalFilter,\n Pagination,\n SortOrder,\n UpdateManyResponse,\n UpdateResponse,\n GetListParams,\n GetManyParams,\n GetOneParams,\n CreateParams,\n CreateManyParams,\n UpdateParams,\n UpdateManyParams,\n DeleteOneParams,\n DeleteManyParams,\n CustomParams,\n DataProvider,\n BaseKey,\n BaseRecord,\n HttpError,\n MetaQuery,\n MetaDataQuery,\n MutationMode,\n Option,\n BaseOption,\n IQueryKeys,\n Prettify,\n Context,\n ContextQuery,\n DataProviders,\n IDataContext,\n GraphQLQueryOptions,\n Fields,\n NestedField,\n PrevContext,\n PreviousQuery,\n QueryBuilderOptions,\n QueryResponse,\n RefineError,\n ValidationErrors,\n VariableOptions,\n} from \"./contexts/data/types.js\";\n\nexport {\n I18nContext,\n I18nContext as TranslationContext,\n} from \"./contexts/i18n/index.js\";\n\nexport {\n I18nProvider,\n I18nProvider as TranslationProvider,\n I18nProvider as i18nBindings,\n II18nContext as ITranslationContext,\n} from \"./contexts/i18n/types.js\";\n\nexport {\n ILiveContext,\n ILiveModeContextProvider,\n LiveEvent,\n LiveCommonParams,\n LiveManyParams,\n LiveModeProps,\n LiveOneParams,\n LiveProvider,\n LiveListParams,\n} from \"./contexts/live/types.js\";\n\nexport {\n INotificationContext,\n NotificationProvider,\n NotificationProvider as NotificationsBindings,\n OpenNotificationParams,\n SuccessErrorNotification,\n} from \"./contexts/notification/types.js\";\n\nexport {\n DashboardPageProps,\n IRefineContext,\n IRefineContextOptions,\n IRefineContextProvider,\n IRefineOptions,\n LayoutProps,\n RefineProps,\n TextTransformers,\n TitleProps,\n} from \"./contexts/refine/types.js\";\n\nexport {\n ResourceProps,\n IResourceComponents,\n IResourceComponentsProps,\n IResourceContext,\n IResourceItem,\n ITreeMenu,\n IMenuItem,\n ResourceAuditLogPermissions,\n ResourceBindings,\n RouteableProperties,\n ResourceRouteComponent,\n ResourceRouteComposition,\n ResourceRouteDefinition,\n ResourceRoutePath,\n} from \"./contexts/resource/types.js\";\n\nexport {\n ActionWithPage,\n LegacyRouterProvider,\n LegacyRouterProvider as IRouterContext,\n LegacyRouterProvider as IRouterProvider,\n PromptProps,\n ResourceErrorRouterParams,\n ResourceRouterParams,\n RouteAction,\n} from \"./contexts/router/legacy/types.js\";\n\nexport {\n Action,\n BackFunction,\n GoConfig,\n GoFunction,\n ParseResponse,\n ParsedParams,\n ParseFunction,\n RouterProvider,\n RouterProvider as RouterBindings,\n} from \"./contexts/router/types.js\";\n\nexport {\n ActionTypes,\n IUndoableQueue,\n IUndoableQueueContext,\n} from \"./contexts/undoableQueue/types.js\";\n\nexport { IUnsavedWarnContext } from \"./contexts/unsavedWarn/types.js\";\n\nexport {\n MetaContextProvider,\n useMetaContext,\n} from \"./contexts/metaContext/index.js\";\n","import React, { useEffect, useState } from \"react\";\n\nimport {\n useNavigation,\n useTranslate,\n useResource,\n useGo,\n useRouterType,\n} from \"@hooks\";\n\n/**\n * When the app is navigated to a non-existent route, refine shows a default error page.\n * A custom error component can be used for this error page.\n *\n * @see {@link https://refine.dev/docs/packages/documentation/routers/} for more details.\n */\nexport const ErrorComponent: React.FC = () => {\n const [errorMessage, setErrorMessage] = useState<string>();\n const translate = useTranslate();\n const { push } = useNavigation();\n const go = useGo();\n const routerType = useRouterType();\n\n const { resource, action } = useResource();\n\n useEffect(() => {\n if (resource && action) {\n setErrorMessage(\n translate(\n \"pages.error.info\",\n {\n action: action,\n resource: resource.name,\n },\n `You may have forgotten to add the \"${action}\" component to \"${resource.name}\" resource.`,\n ),\n );\n }\n }, [resource, action]);\n\n return (\n <>\n <h1>\n {translate(\n \"pages.error.404\",\n undefined,\n \"Sorry, the page you visited does not exist.\",\n )}\n </h1>\n {errorMessage && <p>{errorMessage}</p>}\n <button\n onClick={() => {\n if (routerType === \"legacy\") {\n push(\"/\");\n } else {\n go({ to: \"/\" });\n }\n }}\n >\n {translate(\"pages.error.backHome\", undefined, \"Back Home\")}\n </button>\n </>\n );\n};\n","import { getXRay } from \"@refinedev/devtools-internal\";\nimport {\n type UseQueryOptions,\n type UseQueryResult,\n useQuery,\n} from \"@tanstack/react-query\";\n\nimport { useAuthBindingsContext, useLegacyAuthContext } from \"@contexts/auth\";\nimport { useKeys } from \"@hooks/useKeys\";\n\nimport type { PermissionResponse } from \"../../../contexts/auth/types\";\n\nexport type UsePermissionsLegacyProps<\n TData = any,\n TParams extends Record<string, any> = Record<string, any>,\n> = {\n v3LegacyAuthProviderCompatible: true;\n options?: UseQueryOptions<TData>;\n params?: TParams;\n};\n\nexport type UsePermissionsProps<\n TData = PermissionResponse,\n TParams extends Record<string, any> = Record<string, any>,\n> = {\n v3LegacyAuthProviderCompatible?: false;\n options?: UseQueryOptions<TData>;\n params?: TParams;\n};\n\nexport type UsePermissionsCombinedProps<\n TData = any,\n TParams extends Record<string, any> = Record<string, any>,\n> = {\n v3LegacyAuthProviderCompatible: boolean;\n options?: UseQueryOptions<TData> | UseQueryOptions<PermissionResponse>;\n params?: TParams;\n};\n\nexport type UsePermissionsLegacyReturnType<TData = any> = UseQueryResult<\n TData,\n unknown\n>;\n\nexport type UsePermissionsReturnType<TData = PermissionResponse> =\n UseQueryResult<TData, unknown>;\n\nexport type UsePermissionsCombinedReturnType<TData = any> =\n | UseQueryResult<TData, unknown>\n | UseQueryResult<PermissionResponse, unknown>;\n\nexport function usePermissions<\n TData = any,\n TParams extends Record<string, any> = Record<string, any>,\n>(\n props: UsePermissionsLegacyProps<TData, TParams>,\n): UsePermissionsLegacyReturnType<TData>;\n\nexport function usePermissions<\n TData = PermissionResponse,\n TParams extends Record<string, any> = Record<string, any>,\n>(props?: UsePermissionsProps<TData, TParams>): UsePermissionsReturnType<TData>;\n\nexport function usePermissions<\n TData = any,\n TParams extends Record<string, any> = Record<string, any>,\n>(\n props?: UsePermissionsCombinedProps<TData, TParams>,\n): UsePermissionsCombinedReturnType<TData>;\n\n/**\n * `usePermissions` calls the `getPermissions` method from the {@link https://refine.dev/docs/core/providers/auth-provider `authProvider`} under the hood.\n *\n * @see {@link https://refine.dev/docs/api-reference/core/hooks/auth/usePermissions} for more details.\n *\n * @typeParam TData - Result data of the query\n *\n * @typeParam TParams - Params will be passed to the `getPermissions` method of {@link https://refine.dev/docs/core/providers/auth-provider `authProvider`}.\n *\n */\nexport function usePermissions<\n TData = any,\n TParams extends Record<string, any> = Record<string, any>,\n>({\n v3LegacyAuthProviderCompatible = false,\n options,\n params,\n}:\n | UsePermissionsProps<TData, TParams>\n | UsePermissionsLegacyProps<TData, TParams> = {}):\n | UsePermissionsReturnType\n | UsePermissionsLegacyReturnType<TData> {\n const { getPermissions: legacyGetPermission } = useLegacyAuthContext();\n const { getPermissions } = useAuthBindingsContext();\n const { keys, preferLegacyKeys } = useKeys();\n\n const queryResponse = useQuery<TData>({\n queryKey: keys().auth().action(\"permissions\").get(preferLegacyKeys),\n // Enabled check for `getPermissions` is enough to be sure that it's defined in the query function but TS is not smart enough to know that.\n queryFn: (getPermissions\n ? () => getPermissions(params)\n : () => Promise.resolve(undefined)) as (\n params?: unknown,\n ) => Promise<TData>,\n enabled: !v3LegacyAuthProviderCompatible && !!getPermissions,\n ...(v3LegacyAuthProviderCompatible ? {} : options),\n meta: {\n ...(v3LegacyAuthProviderCompatible ? {} : options?.meta),\n ...getXRay(\"usePermissions\", preferLegacyKeys),\n },\n });\n\n const legacyQueryResponse = useQuery<TData>({\n queryKey: [\n ...keys().auth().action(\"permissions\").get(preferLegacyKeys),\n \"v3LegacyAuthProviderCompatible\",\n ],\n // Enabled check for `getPermissions` is enough to be sure that it's defined in the query function but TS is not smart enough to know that.\n queryFn: (legacyGetPermission\n ? () => legacyGetPermission(params)\n : () => Promise.resolve(undefined)) as (\n params?: unknown,\n ) => Promise<TData>,\n enabled: v3LegacyAuthProviderCompatible && !!legacyGetPermission,\n ...(v3LegacyAuthProviderCompatible ? options : {}),\n meta: {\n ...(v3LegacyAuthProviderCompatible ? options?.meta : {}),\n ...getXRay(\"usePermissions\", preferLegacyKeys),\n },\n });\n\n return v3LegacyAuthProviderCompatible ? legacyQueryResponse : queryResponse;\n}\n","import React, { type PropsWithChildren } from \"react\";\n\nimport { useNavigation } from \"@hooks\";\n\nimport type { IAuthContext, ILegacyAuthContext } from \"./types\";\n\n/**\n * @deprecated `LegacyAuthContext` is deprecated with refine@4, use `AuthBindingsContext` instead, however, we still support `LegacyAuthContext` for backward compatibility.\n */\nexport const LegacyAuthContext = React.createContext<ILegacyAuthContext>({});\n\n/**\n * @deprecated `LegacyAuthContextProvider` is deprecated with refine@4, use `AuthBindingsContextProvider` instead, however, we still support `LegacyAuthContextProvider` for backward compatibility.\n */\nexport const LegacyAuthContextProvider: React.FC<\n PropsWithChildren<ILegacyAuthContext>\n> = ({ children, isProvided, ...authOperations }) => {\n const { replace } = useNavigation();\n\n const loginFunc = async (params: any) => {\n try {\n const result = await authOperations.login?.(params);\n\n return result;\n } catch (error) {\n return Promise.reject(error);\n }\n };\n\n const registerFunc = async (params: any) => {\n try {\n const result = await authOperations.register?.(params);\n\n return result;\n } catch (error) {\n return Promise.reject(error);\n }\n };\n\n const logoutFunc = async (params: any) => {\n try {\n const redirectPath = await authOperations.logout?.(params);\n\n return redirectPath;\n } catch (error) {\n return Promise.reject(error);\n }\n };\n\n const checkAuthFunc = async (params: any) => {\n try {\n await authOperations.checkAuth?.(params);\n return Promise.resolve();\n } catch (error) {\n if ((error as { redirectPath?: string })?.redirectPath) {\n replace((error as { redirectPath: string }).redirectPath);\n }\n\n return Promise.reject(error);\n }\n };\n\n return (\n <LegacyAuthContext.Provider\n value={{\n ...authOperations,\n login: loginFunc,\n logout: logoutFunc,\n checkAuth: checkAuthFunc,\n register: registerFunc,\n isProvided,\n }}\n >\n {children}\n </LegacyAuthContext.Provider>\n );\n};\n\nexport const AuthBindingsContext = React.createContext<Partial<IAuthContext>>(\n {},\n);\n\nexport const AuthBindingsContextProvider: React.FC<\n PropsWithChildren<IAuthContext>\n> = ({ children, isProvided, ...authBindings }) => {\n const handleLogin = async (params: unknown) => {\n try {\n const result = await authBindings.login?.(params);\n\n return result;\n } catch (error) {\n console.warn(\n \"Unhandled Error in login: refine always expects a resolved promise.\",\n error,\n );\n return Promise.reject(error);\n }\n };\n\n const handleRegister = async (params: unknown) => {\n try {\n const result = await authBindings.register?.(params);\n\n return result;\n } catch (error) {\n console.warn(\n \"Unhandled Error in register: refine always expects a resolved promise.\",\n error,\n );\n return Promise.reject(error);\n }\n };\n\n const handleLogout = async (params: unknown) => {\n try {\n const result = await authBindings.logout?.(params);\n\n return result;\n } catch (error) {\n console.warn(\n \"Unhandled Error in logout: refine always expects a resolved promise.\",\n error,\n );\n return Promise.reject(error);\n }\n };\n\n const handleCheck = async (params: unknown) => {\n try {\n const result = await authBindings.check?.(params);\n\n return Promise.resolve(result);\n } catch (error) {\n console.warn(\n \"Unhandled Error in check: refine always expects a resolved promise.\",\n error,\n );\n return Promise.reject(error);\n }\n };\n\n const handleForgotPassword = async (params: unknown) => {\n try {\n const result = await authBindings.forgotPassword?.(params);\n\n return Promise.resolve(result);\n } catch (error) {\n console.warn(\n \"Unhandled Error in forgotPassword: refine always expects a resolved promise.\",\n error,\n );\n return Promise.reject(error);\n }\n };\n\n const handleUpdatePassword = async (params: unknown) => {\n try {\n const result = await authBindings.updatePassword?.(params);\n return Promise.resolve(result);\n } catch (error) {\n console.warn(\n \"Unhandled Error in updatePassword: refine always expects a resolved promise.\",\n error,\n );\n return Promise.reject(error);\n }\n };\n\n return (\n <AuthBindingsContext.Provider\n value={{\n ...authBindings,\n login: handleLogin as IAuthContext[\"login\"],\n logout: handleLogout as IAuthContext[\"logout\"],\n check: handleCheck as IAuthContext[\"check\"],\n register: handleRegister as IAuthContext[\"register\"],\n forgotPassword: handleForgotPassword as IAuthContext[\"forgotPassword\"],\n updatePassword: handleUpdatePassword as IAuthContext[\"updatePassword\"],\n isProvided,\n }}\n >\n {children}\n </AuthBindingsContext.Provider>\n );\n};\n\n/**\n * @deprecated `useLegacyAuthContext` is deprecated with refine@4, use `useAuthBindingsContext` instead, however, we still support `useLegacyAuthContext` for backward compatibility.\n */\nexport const useLegacyAuthContext = () => {\n const context = React.useContext(LegacyAuthContext);\n\n return context;\n};\n\nexport const useAuthBindingsContext = () => {\n const context = React.useContext(AuthBindingsContext);\n\n return context;\n};\n","import differenceWith from \"lodash/differenceWith\";\nimport unionWith from \"lodash/unionWith\";\nimport qs, { type IStringifyOptions } from \"qs\";\nimport warnOnce from \"warn-once\";\n\nimport { pickNotDeprecated } from \"@definitions/helpers\";\n\nimport type {\n CrudFilter,\n CrudOperators,\n CrudSort,\n SortOrder,\n} from \"../../contexts/data/types\";\n\nexport const parseTableParams = (url: string) => {\n const { current, pageSize, sorter, sorters, filters } = qs.parse(\n url.substring(1), // remove first ? character\n );\n\n return {\n parsedCurrent: current && Number(current),\n parsedPageSize: pageSize && Number(pageSize),\n parsedSorter: (pickNotDeprecated(sorters, sorter) as CrudSort[]) ?? [],\n parsedFilters: (filters as CrudFilter[]) ?? [],\n };\n};\n\nexport const parseTableParamsFromQuery = (params: any) => {\n const url = qs.stringify(params);\n return parseTableParams(`/${url}`);\n};\n\n/**\n * @internal This function is used to stringify table params from the useTable hook.\n */\nexport const stringifyTableParams = (params: {\n pagination?: { current?: number; pageSize?: number };\n sorters: CrudSort[];\n filters: CrudFilter[];\n [key: string]: any;\n}): string => {\n const options: IStringifyOptions = {\n skipNulls: true,\n arrayFormat: \"indices\",\n encode: false,\n };\n const { pagination, sorter, sorters, filters, ...rest } = params;\n\n const queryString = qs.stringify(\n {\n ...rest,\n ...(pagination ? pagination : {}),\n sorters: pickNotDeprecated(sorters, sorter),\n filters,\n },\n options,\n );\n\n return queryString;\n};\n\nexport const compareFilters = (\n left: CrudFilter,\n right: CrudFilter,\n): boolean => {\n if (\n left.operator !== \"and\" &&\n left.operator !== \"or\" &&\n right.operator !== \"and\" &&\n right.operator !== \"or\"\n ) {\n return (\n (\"field\" in left ? left.field : undefined) ===\n (\"field\" in right ? right.field : undefined) &&\n left.operator === right.operator\n );\n }\n\n return (\n (\"key\" in left ? left.key : undefined) ===\n (\"key\" in right ? right.key : undefined) &&\n left.operator === right.operator\n );\n};\n\nexport const compareSorters = (left: CrudSort, right: CrudSort): boolean =>\n left.field === right.field;\n// Keep only one CrudFilter per type according to compareFilters\n// Items in the array that is passed first to unionWith have higher priority\n// CrudFilter items with undefined values are necessary to signify no filter\n// After union, don't keep CrudFilter items with undefined value in the result\n// Items in the arrays with higher priority are put at the end.\nexport const unionFilters = (\n permanentFilter: CrudFilter[],\n newFilters: CrudFilter[],\n prevFilters: CrudFilter[] = [],\n): CrudFilter[] => {\n const isKeyRequired = newFilters.filter(\n (f) => (f.operator === \"or\" || f.operator === \"and\") && !f.key,\n );\n\n if (isKeyRequired.length > 1) {\n warnOnce(\n true,\n \"[conditionalFilters]: You have created multiple Conditional Filters at the top level, this requires the key parameter. \\nFor more information, see https://refine.dev/docs/advanced-tutorials/data-provider/handling-filters/#top-level-multiple-conditional-filters-usage\",\n );\n }\n\n return unionWith(\n permanentFilter,\n newFilters,\n prevFilters,\n compareFilters,\n ).filter(\n (crudFilter) =>\n crudFilter.value !== undefined &&\n crudFilter.value !== null &&\n (crudFilter.operator !== \"or\" ||\n (crudFilter.operator === \"or\" && crudFilter.value.length !== 0)) &&\n (crudFilter.operator !== \"and\" ||\n (crudFilter.operator === \"and\" && crudFilter.value.length !== 0)),\n );\n};\n\nexport const unionSorters = (\n permanentSorter: CrudSort[],\n newSorters: CrudSort[],\n): CrudSort[] =>\n unionWith(permanentSorter, newSorters, compareSorters).filter(\n (crudSorter) => crudSorter.order !== undefined && crudSorter.order !== null,\n );\n// Prioritize filters in the permanentFilter and put it at the end of result array\nexport const setInitialFilters = (\n permanentFilter: CrudFilter[],\n defaultFilter: CrudFilter[],\n): CrudFilter[] => [\n ...differenceWith(defaultFilter, permanentFilter, compareFilters),\n ...permanentFilter,\n];\n\nexport const setInitialSorters = (\n permanentSorter: CrudSort[],\n defaultSorter: CrudSort[],\n): CrudSort[] => [\n ...differenceWith(defaultSorter, permanentSorter, compareSorters),\n ...permanentSorter,\n];\n\nexport const getDefaultSortOrder = (\n columnName: string,\n sorter?: CrudSort[],\n): SortOrder | undefined => {\n if (!sorter) {\n return undefined;\n }\n\n const sortItem = sorter.find((item) => item.field === columnName);\n\n if (sortItem) {\n return sortItem.order as SortOrder;\n }\n\n return undefined;\n};\n\nexport const getDefaultFilter = (\n columnName: string,\n filters?: CrudFilter[],\n operatorType: CrudOperators = \"eq\",\n): CrudFilter[\"value\"] | undefined => {\n const filter = filters?.find((filter) => {\n if (\n filter.operator !== \"or\" &&\n filter.operator !== \"and\" &&\n \"field\" in filter\n ) {\n const { operator, field } = filter;\n return field === columnName && operator === operatorType;\n }\n return undefined;\n });\n\n if (filter) {\n return filter.value || [];\n }\n\n return undefined;\n};\n","export const userFriendlySecond = (miliseconds: number): number => {\n return miliseconds / 1000; //convert to seconds\n};\n","import fromPairs from \"lodash/fromPairs\";\nimport zip from \"lodash/zip\";\n\nimport type { MapDataFn } from \"../../../hooks/export/types\";\n\nexport const importCSVMapper = <TItem = any, TVariables = any>(\n data: any[][],\n mapData: MapDataFn<TItem, TVariables> = (item) => item as any,\n): TVariables[] => {\n const [headers, ...body] = data;\n return body\n .map((entry) => fromPairs(zip(headers, entry)))\n .map((item: any, index, array: any) =>\n mapData.call(undefined, item, index, array),\n );\n};\n","import pluralize from \"pluralize\";\nimport { humanizeString } from \"@definitions\";\n\n/**\n * A method that the internal uses\n * @internal\n * @deprecated use `useUserFriendlyName` instead.\n */\nexport const userFriendlyResourceName = (\n resource = \"\",\n type: \"singular\" | \"plural\",\n): string => {\n const humanizeResource = humanizeString(resource);\n if (type === \"singular\") {\n return pluralize.singular(humanizeResource);\n }\n return pluralize.plural(humanizeResource);\n};\n","export const handleUseParams = (params: any = {}): any => {\n if (params?.id) {\n return {\n ...params,\n id: decodeURIComponent(params.id),\n };\n }\n return params;\n};\n","import type { BaseKey } from \"../../../contexts/data/types\";\n\ntype ParametrizedDataActions = \"list\" | \"infinite\";\ntype IdRequiredDataActions = \"one\";\ntype IdsRequiredDataActions = \"many\";\ntype DataMutationActions =\n | \"custom\"\n | \"customMutation\"\n | \"create\"\n | \"createMany\"\n | \"update\"\n | \"updateMany\"\n | \"delete\"\n | \"deleteMany\";\n\ntype AuthActionType =\n | \"login\"\n | \"logout\"\n | \"identity\"\n | \"register\"\n | \"forgotPassword\"\n | \"check\"\n | \"onError\"\n | \"permissions\"\n | \"updatePassword\";\n\ntype AuditActionType = \"list\" | \"log\" | \"rename\";\n\ntype IdType = BaseKey;\ntype IdsType = IdType[];\n\ntype ParamsType = any;\n\ntype KeySegment = string | IdType | IdsType | ParamsType;\n\nexport function arrayFindIndex<T>(array: T[], slice: T[]): number {\n return array.findIndex(\n (item, index) =>\n index <= array.length - slice.length &&\n slice.every(\n (sliceItem, sliceIndex) => array[index + sliceIndex] === sliceItem,\n ),\n );\n}\n\nexport function arrayReplace<T>(\n array: T[],\n partToBeReplaced: T[],\n newPart: T[],\n): T[] {\n const newArray: T[] = [...array];\n const startIndex = arrayFindIndex(array, partToBeReplaced);\n\n if (startIndex !== -1) {\n newArray.splice(startIndex, partToBeReplaced.length, ...newPart);\n }\n\n return newArray;\n}\n\nexport function stripUndefined(segments: KeySegment[]) {\n return segments.filter((segment) => segment !== undefined);\n}\n\nfunction convertToLegacy(segments: KeySegment[]) {\n // for `list`, `many` and `one`\n if (segments[0] === \"data\") {\n // [data, dpName, resource, action, ...];\n const newSegments = segments.slice(1);\n\n if (newSegments[2] === \"many\") {\n newSegments[2] = \"getMany\";\n } else if (newSegments[2] === \"infinite\") {\n newSegments[2] = \"list\";\n } else if (newSegments[2] === \"one\") {\n newSegments[2] = \"detail\";\n } else if (newSegments[1] === \"custom\") {\n const newParams = {\n ...newSegments[2],\n };\n delete newParams.method;\n delete newParams.url;\n\n return [\n newSegments[0],\n newSegments[1],\n newSegments[2].method,\n newSegments[2].url,\n newParams,\n ];\n }\n\n return newSegments;\n }\n // for `audit` -> `logList`\n if (segments[0] === \"audit\") {\n // [audit, resource, action, params] (for log and list)\n // or\n // [audit, action, params] (for rename)\n if (segments[2] === \"list\") {\n return [\"logList\", segments[1], segments[3]];\n }\n }\n // for `access` -> `useCan`\n if (segments[0] === \"access\") {\n // [access, resource, action, params]\n if (segments.length === 4) {\n return [\n \"useCan\",\n {\n resource: segments[1],\n action: segments[2],\n ...segments[3], // params: { params, enabled }\n },\n ];\n }\n }\n // for `auth`\n if (segments[0] === \"auth\") {\n if (arrayFindIndex(segments, [\"auth\", \"login\"]) !== -1) {\n return [\"useLogin\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"logout\"]) !== -1) {\n return [\"useLogout\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"identity\"]) !== -1) {\n return [\"getUserIdentity\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"register\"]) !== -1) {\n return [\"useRegister\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"forgotPassword\"]) !== -1) {\n return [\"useForgotPassword\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"check\"]) !== -1) {\n return [\"useAuthenticated\", segments[2]]; // [auth, check, params]\n }\n if (arrayFindIndex(segments, [\"auth\", \"onError\"]) !== -1) {\n return [\"useCheckError\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"permissions\"]) !== -1) {\n return [\"usePermissions\"];\n }\n if (arrayFindIndex(segments, [\"auth\", \"updatePassword\"]) !== -1) {\n return [\"useUpdatePassword\"];\n }\n }\n return segments;\n}\n\nclass BaseKeyBuilder {\n segments: KeySegment[] = [];\n\n constructor(segments: KeySegment[] = []) {\n this.segments = segments;\n }\n\n key() {\n return this.segments;\n }\n\n legacy() {\n return convertToLegacy(this.segments);\n }\n\n get(legacy?: boolean) {\n return legacy ? this.legacy() : this.segments;\n }\n}\n\nclass ParamsKeyBuilder extends BaseKeyBuilder {\n params(paramsValue?: ParamsType) {\n return new BaseKeyBuilder([...this.segments, paramsValue]);\n }\n}\n\nclass DataIdRequiringKeyBuilder extends BaseKeyBuilder {\n id(idValue?: IdType) {\n return new ParamsKeyBuilder([\n ...this.segments,\n idValue ? String(idValue) : undefined,\n ]);\n }\n}\n\nclass DataIdsRequiringKeyBuilder extends BaseKeyBuilder {\n ids(...idsValue: IdsType) {\n return new ParamsKeyBuilder([\n ...this.segments,\n ...(idsValue.length ? [idsValue.map((el) => String(el))] : []),\n ]);\n }\n}\n\nclass DataResourceKeyBuilder extends BaseKeyBuilder {\n action(actionType: ParametrizedDataActions): ParamsKeyBuilder;\n action(actionType: IdRequiredDataActions): DataIdRequiringKeyBuilder;\n action(actionType: IdsRequiredDataActions): DataIdsRequiringKeyBuilder;\n action(\n actionType:\n | ParametrizedDataActions\n | IdRequiredDataActions\n | IdsRequiredDataActions,\n ): ParamsKeyBuilder | DataIdRequiringKeyBuilder | DataIdsRequiringKeyBuilder {\n if (actionType === \"one\") {\n return new DataIdRequiringKeyBuilder([...this.segments, actionType]);\n }\n if (actionType === \"many\") {\n return new DataIdsRequiringKeyBuilder([...this.segments, actionType]);\n }\n if ([\"list\", \"infinite\"].includes(actionType)) {\n return new ParamsKeyBuilder([...this.segments, actionType]);\n }\n throw new Error(\"Invalid action type\");\n }\n}\n\nclass DataKeyBuilder extends BaseKeyBuilder {\n resource(resourceName?: string) {\n return new DataResourceKeyBuilder([...this.segments, resourceName]);\n }\n\n mutation(mutationName: DataMutationActions) {\n return new ParamsKeyBuilder([\n ...(mutationName === \"custom\" ? this.segments : [this.segments[0]]),\n mutationName,\n ]);\n }\n}\n\nclass AuthKeyBuilder extends BaseKeyBuilder {\n action(actionType: AuthActionType) {\n return new ParamsKeyBuilder([...this.segments, actionType]);\n }\n}\n\nclass AccessResourceKeyBuilder extends BaseKeyBuilder {\n action(resourceName: string) {\n return new ParamsKeyBuilder([...this.segments, resourceName]);\n }\n}\n\nclass AccessKeyBuilder extends BaseKeyBuilder {\n resource(resourceName?: string) {\n return new AccessResourceKeyBuilder([...this.segments, resourceName]);\n }\n}\n\nclass AuditActionKeyBuilder extends BaseKeyBuilder {\n action(actionType: Extract<AuditActionType, \"list\">) {\n return new ParamsKeyBuilder([...this.segments, actionType]);\n }\n}\n\nclass AuditKeyBuilder extends BaseKeyBuilder {\n resource(resourceName?: string) {\n return new AuditActionKeyBuilder([...this.segments, resourceName]);\n }\n\n action(actionType: Extract<AuditActionType, \"rename\" | \"log\">) {\n return new ParamsKeyBuilder([...this.segments, actionType]);\n }\n}\n\nexport class KeyBuilder extends BaseKeyBuilder {\n data(name?: string) {\n return new DataKeyBuilder([\"data\", name || \"default\"]);\n }\n\n auth() {\n return new AuthKeyBuilder([\"auth\"]);\n }\n\n access() {\n return new AccessKeyBuilder([\"access\"]);\n }\n\n audit() {\n return new AuditKeyBuilder([\"audit\"]);\n }\n}\n\nexport const keys = () => new KeyBuilder([]);\n","/*\n * Returns first value that is not undefined.\n * @internal This is an internal helper function. Please do not use externally.\n */\nexport const pickNotDeprecated = <T extends unknown[]>(\n ...args: T\n): T[never] => {\n return args.find((arg) => typeof arg !== \"undefined\");\n};\n","import type { QueryKey } from \"@tanstack/react-query\";\n\nimport type { IQueryKeys, MetaQuery } from \"../../../contexts/data/types\";\nimport { keys as newKeys } from \"../keys\";\nimport { pickNotDeprecated } from \"../pickNotDeprecated\";\n\n/**\n * @deprecated `queryKeys` is deprecated. Please use `keys` instead.\n */\nexport const queryKeys = (\n resource?: string,\n dataProviderName?: string,\n meta?: MetaQuery,\n /**\n * @deprecated `metaData` is deprecated with refine@4, refine will pass `meta` instead, however, we still support `metaData` for backward compatibility.\n */\n metaData?: MetaQuery | undefined,\n): IQueryKeys => {\n const providerName = dataProviderName || \"default\";\n const keys: IQueryKeys = {\n all: [providerName],\n resourceAll: [providerName, resource || \"\"],\n list: (config) => [\n ...keys.resourceAll,\n \"list\",\n {\n ...config,\n ...(pickNotDeprecated(meta, metaData) || {}),\n } as QueryKey,\n ],\n many: (ids) =>\n [\n ...keys.resourceAll,\n \"getMany\",\n ids?.map(String) as QueryKey,\n { ...(pickNotDeprecated(meta, metaData) || {}) } as QueryKey,\n ].filter((item) => item !== undefined),\n detail: (id) => [\n ...keys.resourceAll,\n \"detail\",\n id?.toString(),\n { ...(pickNotDeprecated(meta, metaData) || {}) } as QueryKey,\n ],\n logList: (meta) =>\n [\"logList\", resource, meta as any, metaData as QueryKey].filter(\n (item) => item !== undefined,\n ),\n };\n return keys;\n};\n\nexport const queryKeysReplacement = (preferLegacyKeys?: boolean) => {\n return (\n resource?: string,\n dataProviderName?: string,\n meta?: MetaQuery,\n /**\n * @deprecated `metaData` is deprecated with refine@4, refine will pass `meta` instead, however, we still support `metaData` for backward compatibility.\n */\n metaData?: MetaQuery | undefined,\n ): IQueryKeys => {\n const providerName = dataProviderName || \"default\";\n\n const keys: IQueryKeys = {\n all: newKeys().data(providerName).get(preferLegacyKeys),\n resourceAll: newKeys()\n .data(dataProviderName)\n .resource(resource ?? \"\")\n .get(preferLegacyKeys),\n list: (config) =>\n newKeys()\n .data(dataProviderName)\n .resource(resource ?? \"\")\n .action(\"list\")\n .params({\n ...config,\n ...(pickNotDeprecated(meta, metaData) || {}),\n })\n .get(preferLegacyKeys),\n many: (ids) =>\n newKeys()\n .data(dataProviderName)\n .resource(resource ?? \"\")\n .action(\"many\")\n .ids(...(ids ?? []))\n .params({\n ...(pickNotDeprecated(meta, metaData) || {}),\n })\n .get(preferLegacyKeys),\n detail: (id) =>\n newKeys()\n .data(dataProviderName)\n .resource(resource ?? \"\")\n .action(\"one\")\n .id(id ?? \"\")\n .params({\n ...(pickNotDeprecated(meta, metaData) || {}),\n })\n .get(preferLegacyKeys),\n logList: (meta) =>\n [\n ...newKeys()\n .audit()\n .resource(resource)\n .action(\"list\")\n .params(meta)\n .get(preferLegacyKeys),\n metaData as QueryKey,\n ].filter((item) => item !== undefined),\n };\n\n return keys;\n };\n};\n","export const hasPermission = (\n permissions: string[] | undefined,\n action: string | undefined,\n): boolean => {\n if (!permissions || !action) {\n return false;\n }\n return !!permissions.find((i) => i === action);\n};\n","/**\n * Check if a segment is a parameter. (e.g. :id)\n */\nexport const isParameter = (segment: string) => {\n return segment.startsWith(\":\");\n};\n","/**\n * Split a path to segments.\n */\nexport const splitToSegments = (path: string) => {\n const segments = path.split(\"/\").filter((segment) => segment !== \"\");\n return segments;\n};\n","import { splitToSegments } from \"./split-to-segments\";\n\n/**\n * Checks if the both routes have the same number of segments.\n */\nexport const isSegmentCountsSame = (route: string, resourceRoute: string) => {\n const routeSegments = splitToSegments(route);\n const resourceRouteSegments = splitToSegments(resourceRoute);\n\n return routeSegments.length === resourceRouteSegments.length;\n};\n","/**\n * Remove leading and trailing slashes from a route.\n */\nexport const removeLeadingTrailingSlashes = (route: string) => {\n return route.replace(/^\\/|\\/$/g, \"\");\n};\n","import { isParameter } from \"./is-parameter\";\nimport { isSegmentCountsSame } from \"./is-segment-counts-same\";\nimport { removeLeadingTrailingSlashes } from \"./remove-leading-trailing-slashes\";\nimport { splitToSegments } from \"./split-to-segments\";\n\n/**\n * This function if the route and resourceRoute match by segments.\n * - First, trailing and leading slashes are removed\n * - Then, the route and resourceRoute are split to segments and checked if they have the same number of segments\n * - Then, each segment is checked if it is a parameter or if it matches the resourceRoute segment\n * - If all segments match, the function returns true, otherwise false\n */\nexport const checkBySegments = (route: string, resourceRoute: string) => {\n const stdRoute = removeLeadingTrailingSlashes(route);\n const stdResourceRoute = removeLeadingTrailingSlashes(resourceRoute);\n // we need to check if the route and resourceRoute have the same number of segments\n // if not, we can't match them\n if (!isSegmentCountsSame(stdRoute, stdResourceRoute)) {\n return false;\n }\n\n const routeSegments = splitToSegments(stdRoute);\n const resourceRouteSegments = splitToSegments(stdResourceRoute);\n\n return resourceRouteSegments.every((segment, index) => {\n return isParameter(segment) || segment === routeSegments[index];\n });\n};\n","import type { Action } from \"../../../contexts/router/types\";\nimport { removeLeadingTrailingSlashes } from \"./remove-leading-trailing-slashes\";\n\n/**\n * This helper function returns the default path for a given action and resource.\n * It also applies the parentPrefix if provided.\n * This is used by the legacy router and the new router if the resource doesn't provide a custom path.\n */\nexport const getDefaultActionPath = (\n resourceName: string,\n action: Action,\n parentPrefix?: string,\n): string => {\n const cleanParentPrefix = removeLeadingTrailingSlashes(parentPrefix || \"\");\n\n let path = `${cleanParentPrefix}${\n cleanParentPrefix ? \"/\" : \"\"\n }${resourceName}`;\n\n if (action === \"list\") {\n path = `${path}`;\n } else if (action === \"create\") {\n path = `${path}/create`;\n } else if (action === \"edit\") {\n path = `${path}/edit/:id`;\n } else if (action === \"show\") {\n path = `${path}/show/:id`;\n } else if (action === \"clone\") {\n path = `${path}/clone/:id`;\n }\n\n return `/${path.replace(/^\\//, \"\")}`;\n};\n","import type { IResourceItem } from \"../../../contexts/resource/types\";\nimport { pickNotDeprecated } from \"../pickNotDeprecated\";\n\n/**\n * Returns the parent resource of the given resource.\n * Works both with the deprecated `parentName` and the new `parent` property.\n */\nexport const getParentResource = (\n resource: IResourceItem,\n resources: IResourceItem[],\n): IResourceItem | undefined => {\n const parentName = pickNotDeprecated(\n resource.meta?.parent,\n resource.options?.parent,\n resource.parentName,\n );\n\n if (!parentName) {\n return undefined;\n }\n\n const parentResource = resources.find(\n (resource) => (resource.identifier ?? resource.name) === parentName,\n );\n\n /**\n * If the parent resource is not found, we return a resource object with the name of the parent resource.\n * Because we still want to have nesting and prefixing for the resource even if the parent is not explicitly defined.\n */\n return parentResource ?? { name: parentName };\n};\n","import type { ResourceProps } from \"../../../contexts/resource/types\";\nimport { getParentResource } from \"./get-parent-resource\";\nimport { removeLeadingTrailingSlashes } from \"./remove-leading-trailing-slashes\";\n\n/**\n * Returns the parent prefix for a resource\n * - If `legacy` is provided, the computation is based on the `route` option of the resource\n */\nexport const getParentPrefixForResource = (\n resource: ResourceProps,\n resources: ResourceProps[],\n /**\n * Uses legacy route if true (`options.route`)\n */\n legacy?: boolean,\n): string | undefined => {\n const parents: ResourceProps[] = [];\n\n let parent = getParentResource(resource, resources);\n\n while (parent) {\n parents.push(parent);\n parent = getParentResource(parent, resources);\n }\n\n if (parents.length === 0) {\n return undefined;\n }\n\n return `/${parents\n .reverse()\n .map((parent) => {\n const v = legacy ? parent.options?.route ?? parent.name : parent.name;\n return removeLeadingTrailingSlashes(v);\n })\n .join(\"/\")}`;\n};\n","import type { IResourceItem } from \"../../../contexts/resource/types\";\nimport type { Action } from \"../../../contexts/router/types\";\nimport { getDefaultActionPath } from \"./get-default-action-path\";\nimport { getParentPrefixForResource } from \"./get-parent-prefix-for-resource\";\n\nexport type ResourceActionRoute = {\n action: Action;\n resource: IResourceItem;\n route: string;\n};\n\n/**\n * This function returns all the routes for available actions for a resource.\n * - If the action is a function, it means we're fallbacking to default path for the action\n * - If the action is a string, it means we don't have the component, but we ha