@refinedev/core
Version:
Refine is a React meta-framework for building enterprise-level, data-intensive applications rapidly with support for modern UI libraries and headless integrations.
1 lines • 619 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/handleUseParams/index.tsx","../src/definitions/helpers/hasPermission/index.ts","../src/definitions/helpers/humanizeString/index.ts","../src/contexts/refine/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/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-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/router/get-parent-resource.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/hooks/refine/useMutationMode.ts","../src/hooks/refine/useWarnAboutChange/index.ts","../src/contexts/unsavedWarn/index.tsx","../src/hooks/refine/useSyncWithLocation.ts","../src/hooks/refine/useRefineContext.ts","../src/definitions/helpers/useUserFriendlyName/index.ts","../src/definitions/helpers/generateDocumentTitle/index.ts","../src/definitions/helpers/keys/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/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-go/index.tsx","../src/contexts/router/index.tsx","../src/hooks/use-resource-params/index.ts","../src/contexts/resource/index.tsx","../src/hooks/deepMemo/index.tsx","../src/hooks/memoized/index.tsx","../src/hooks/router/use-parsed/index.tsx","../src/hooks/router/use-parse/index.tsx","../src/hooks/use-resource-params/use-id/index.tsx","../src/hooks/use-resource-params/use-action/index.tsx","../src/hooks/use-resource-params/use-resource/index.ts","../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-back/index.tsx","../src/hooks/router/use-to-path/index.ts","../src/components/link/index.tsx","../src/hooks/router/use-link/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/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/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/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/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\";\n\nexport {\n getDefaultFilter,\n getDefaultSortOrder,\n parseTableParams,\n parseTableParamsFromQuery,\n QS_PARSE_DEPTH,\n setInitialFilters,\n setInitialSorters,\n stringifyTableParams,\n unionFilters,\n unionSorters,\n} from \"./definitions/table/index.js\";\nexport {\n handleUseParams,\n importCSVMapper,\n getNextPageParam,\n getPreviousPageParam,\n matchResourceFromRoute,\n useActiveAuthProvider,\n useUserFriendlyName,\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 AuthProvider,\n CheckResponse,\n IAuthContext,\n IdentityResponse,\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 MutationMode,\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 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 ResourceAuditLogPermissions,\n ResourceBindings,\n RouteableProperties,\n ResourceRoutePath,\n} from \"./contexts/resource/types.js\";\n\nexport {\n Action,\n BackFunction,\n GoConfig,\n GoFunction,\n ParseResponse,\n ParsedParams,\n ParseFunction,\n RouterProvider,\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\nexport { TreeMenuItem, UseMenuProps } from \"./hooks/menu/useMenu.js\";\n","import React, { useEffect, useState } from \"react\";\n\nimport { useTranslate, useGo, useResourceParams } 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 go = useGo();\n\n const { action, resource } = useResourceParams();\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 go({ to: \"/\" });\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 { useAuthProviderContext } from \"@contexts/auth\";\nimport { useKeys } from \"@hooks/useKeys\";\nimport type { PermissionResponse } from \"../../../contexts/auth/types\";\n\nexport type UsePermissionsProps<\n TData = PermissionResponse,\n TParams extends Record<string, any> = Record<string, any>,\n> = {\n options?: UseQueryOptions<TData>;\n params?: TParams;\n};\nexport type UsePermissionsReturnType<TData = PermissionResponse> =\n UseQueryResult<TData, unknown>;\n\n/**\n * `usePermissions` calls `getPermissions` method from {@link https://refine.dev/docs/api-reference/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 */\nexport function usePermissions<\n TData = any,\n TParams extends Record<string, any> = Record<string, any>,\n>({\n options,\n params,\n}: UsePermissionsProps<TData, TParams>): UsePermissionsReturnType<TData> {\n const { getPermissions } = useAuthProviderContext();\n const { keys } = useKeys();\n\n const queryResponse = useQuery<TData>({\n queryKey: keys().auth().action(\"permissions\").get(),\n queryFn: (getPermissions\n ? () => getPermissions(params)\n : () => Promise.resolve(undefined)) as (\n params?: unknown,\n ) => Promise<TData>,\n enabled: !!getPermissions,\n ...options,\n meta: {\n ...options?.meta,\n ...getXRay(\"usePermissions\"),\n },\n });\n\n return queryResponse;\n}\n","import React, { type PropsWithChildren } from \"react\";\n\nimport type { IAuthContext } from \"./types\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nexport const AuthProviderContext = React.createContext<Partial<IAuthContext>>(\n {},\n);\n\nexport const AuthProviderContextProvider: React.FC<\n PropsWithChildren<IAuthContext>\n> = ({ children, isProvided, ...authProvider }) => {\n const queryClient = useQueryClient();\n\n const handleLogin = async (params: unknown) => {\n try {\n const result = await authProvider.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 authProvider.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 authProvider.logout?.(params);\n queryClient.invalidateQueries();\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 authProvider.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 authProvider.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 authProvider.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 <AuthProviderContext.Provider\n value={{\n ...authProvider,\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 </AuthProviderContext.Provider>\n );\n};\n\nexport const useAuthProviderContext = () => {\n const context = React.useContext(AuthProviderContext);\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 type {\n CrudFilter,\n CrudOperators,\n CrudSort,\n SortOrder,\n} from \"../../contexts/data/types\";\n\n/**\n * Depth limit for `qs.parse`. Deeply nested conditional filters\n * (e.g. `or -> and -> { field, operator, value }`) require at least 7 levels.\n * We use 10 to leave comfortable headroom.\n */\nexport const QS_PARSE_DEPTH = 10;\n\nexport const parseTableParams = (url: string) => {\n const { currentPage, pageSize, sorters, sorter, filters } = qs.parse(\n url.substring(1), // remove first ? character\n { depth: QS_PARSE_DEPTH },\n );\n\n return {\n parsedCurrentPage: currentPage && Number(currentPage),\n parsedPageSize: pageSize && Number(pageSize),\n parsedSorter: (sorters as CrudSort[]) || (sorter as CrudSort[]) || [],\n parsedFilters: (filters as CrudFilter[]) ?? [],\n };\n};\n\nexport const parseTableParamsFromQuery = (params: any) => {\n const { currentPage, pageSize, sorters, sorter, filters } = params;\n\n return {\n parsedCurrentPage: currentPage && Number(currentPage),\n parsedPageSize: pageSize && Number(pageSize),\n parsedSorter: (sorters as CrudSort[]) || (sorter as CrudSort[]) || [],\n parsedFilters: (filters as CrudFilter[]) ?? [],\n };\n};\n\n/**\n * @internal This function is used to stringify table params from the useTable hook.\n */\nexport const stringifyTableParams = (params: {\n pagination?: { currentPage?: number; pageSize?: number };\n sorters: CrudSort[];\n sorter?: CrudSort[];\n filters: CrudFilter[];\n [key: string]: any;\n}): string => {\n // Note: qs.stringify has no depth limit by default, so it correctly\n // serialises deeply nested filters without extra configuration.\n // The matching qs.parse call uses QS_PARSE_DEPTH to deserialise them.\n const options: IStringifyOptions = {\n skipNulls: true,\n arrayFormat: \"indices\",\n encode: false,\n };\n const { pagination, sorters, sorter, filters, ...rest } = params;\n\n // Prioritize sorters over sorter\n const finalSorters = sorters && sorters.length > 0 ? sorters : sorter;\n\n const queryString = qs.stringify(\n {\n ...rest,\n ...(pagination ? pagination : {}),\n sorters: finalSorters,\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","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","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","export const humanizeString = (text: string): string => {\n text = text.replace(/([a-z]{1})([A-Z]{1})/g, \"$1-$2\");\n text = text.replace(/([A-Z]{1})([A-Z]{1})([a-z]{1})/g, \"$1-$2$3\");\n\n text = text\n .toLowerCase()\n .replace(/[_-]+/g, \" \")\n .replace(/\\s{2,}/g, \" \")\n .trim();\n text = text.charAt(0).toUpperCase() + text.slice(1);\n\n return text;\n};\n// https://www.npmjs.com/package/humanize-string\n","import React from \"react\";\n\nimport pluralize from \"pluralize\";\n\nimport { humanizeString } from \"../../definitions/helpers/humanizeString\";\nimport type {\n IRefineContext,\n IRefineContextOptions,\n IRefineContextProvider,\n} from \"./types\";\n\nconst defaultTitle: IRefineContextOptions[\"title\"] = {\n icon: (\n <svg\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"refine-logo\"\n id=\"refine-default-logo\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M13.7889 0.422291C12.6627 -0.140764 11.3373 -0.140764 10.2111 0.422291L2.21115 4.42229C0.85601 5.09986 0 6.48491 0 8V16C0 17.5151 0.85601 18.9001 2.21115 19.5777L10.2111 23.5777C11.3373 24.1408 12.6627 24.1408 13.7889 23.5777L21.7889 19.5777C23.144 18.9001 24 17.5151 24 16V8C24 6.48491 23.144 5.09986 21.7889 4.42229L13.7889 0.422291ZM8 8C8 5.79086 9.79086 4 12 4C14.2091 4 16 5.79086 16 8V16C16 18.2091 14.2091 20 12 20C9.79086 20 8 18.2091 8 16V8Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M14 8C14 9.10457 13.1046 10 12 10C10.8954 10 10 9.10457 10 8C10 6.89543 10.8954 6 12 6C13.1046 6 14 6.89543 14 8Z\"\n fill=\"currentColor\"\n />\n </svg>\n ),\n text: \"Refine Project\",\n};\n\nexport const defaultRefineOptions: IRefineContextOptions = {\n mutationMode: \"pessimistic\",\n syncWithLocation: false,\n undoableTimeout: 5000,\n warnWhenUnsavedChanges: false,\n liveMode: \"off\",\n redirect: {\n afterCreate: \"list\",\n afterClone: \"list\",\n afterEdit: \"list\",\n },\n overtime: {\n enabled: true,\n interval: 1000,\n },\n textTransformers: {\n humanize: humanizeString,\n plural: pluralize.plural,\n singular: pluralize.singular,\n },\n disableServerSideValidation: false,\n disableRouteChangeHandler: false,\n title: defaultTitle,\n};\n\nexport const RefineContext = React.createContext<IRefineContext>({\n mutationMode: \"pessimistic\",\n warnWhenUnsavedChanges: false,\n syncWithLocation: false,\n undoableTimeout: 5000,\n liveMode: \"off\",\n onLiveEvent: undefined,\n options: defaultRefineOptions,\n});\n\nexport const RefineContextProvider: React.FC<IRefineContextProvider> = ({\n mutationMode,\n warnWhenUnsavedChanges,\n syncWithLocation,\n undoableTimeout,\n children,\n liveMode = \"off\",\n onLiveEvent,\n options,\n}) => {\n return (\n <RefineContext.Provider\n value={{\n __initialized: true,\n mutationMode,\n warnWhenUnsavedChanges,\n syncWithLocation,\n undoableTimeout,\n liveMode,\n onLiveEvent,\n options,\n }}\n >\n {children}\n </RefineContext.Provider>\n );\n};\n","import type { QueryClient, QueryClientConfig } from \"@tanstack/react-query\";\n\nimport { defaultRefineOptions } from \"@contexts/refine\";\n\nimport type { MutationMode } from \"../../../contexts/data/types\";\nimport type { LiveModeProps } from \"../../../contexts/live/types\";\nimport type {\n IRefineContextOptions,\n IRefineOptions,\n} from \"../../../contexts/refine/types\";\n\ntype HandleRefineOptionsProps = {\n options?: IRefineOptions;\n mutationMode?: MutationMode;\n syncWithLocation?: boolean;\n warnWhenUnsavedChanges?: boolean;\n undoableTimeout?: number;\n liveMode?: LiveModeProps[\"liveMode\"];\n disableTelemetry?: boolean;\n disableRouteChangeHandler?: boolean;\n reactQueryClientConfig?: QueryClientConfig;\n reactQueryDevtoolConfig?: any | false;\n};\n\ntype HandleRefineOptionsReturnValues = {\n optionsWithDefaults: IRefineContextOptions;\n disableTelemetryWithDefault: boolean;\n reactQueryWithDefaults: {\n clientConfig: QueryClientConfig | InstanceType<typeof QueryClient>;\n };\n};\n\nexport const handleRefineOptions = ({\n options,\n disableTelemetry,\n liveMode,\n mutationMode,\n reactQueryClientConfig,\n reactQueryDevtoolConfig,\n syncWithLocation,\n undoableTimeout,\n warnWhenUnsavedChanges,\n disableRouteChangeHandler,\n}: HandleRefineOptionsProps = {}): HandleRefineOptionsReturnValues => {\n const optionsWithDefaults: IRefineContextOptions = {\n breadcrumb: options?.breadcrumb,\n mutationMode:\n options?.mutationMode ??\n mutationMode ??\n defaultRefineOptions.mutationMode,\n undoableTimeout:\n options?.undoableTimeout ??\n undoableTimeout ??\n defaultRefineOptions.undoableTimeout,\n syncWithLocation:\n options?.syncWithLocation ??\n syncWithLocation ??\n defaultRefineOptions.syncWithLocation,\n warnWhenUnsavedChanges:\n options?.warnWhenUnsavedChanges ??\n warnWhenUnsavedChanges ??\n defaultRefineOptions.warnWhenUnsavedChanges,\n liveMode: options?.liveMode ?? liveMode ?? defaultRefineOptions.liveMode,\n redirect: {\n afterCreate:\n options?.redirect?.afterCreate ??\n defaultRefineOptions.redirect.afterCreate,\n afterClone:\n options?.redirect?.afterClone ??\n defaultRefineOptions.redirect.afterClone,\n afterEdit:\n options?.redirect?.afterEdit ?? defaultRefineOptions.redirect.afterEdit,\n },\n overtime: options?.overtime ?? defaultRefineOptions.overtime,\n textTransformers: {\n humanize:\n options?.textTransformers?.humanize ??\n defaultRefineOptions.textTransformers.humanize,\n plural:\n options?.textTransformers?.plural ??\n defaultRefineOptions.textTransformers.plural,\n singular:\n options?.textTransformers?.singular ??\n defaultRefineOptions.textTransformers.singular,\n },\n disableServerSideValidation:\n options?.disableServerSideValidation ??\n defaultRefineOptions.disableServerSideValidation,\n projectId: options?.projectId,\n title: {\n icon:\n typeof options?.title?.icon === \"undefined\"\n ? defaultRefineOptions.title.icon\n : options?.title?.icon,\n text:\n typeof options?.title?.text === \"undefined\"\n ? defaultRefineOptions.title.text\n : options?.title?.text,\n },\n disableRouteChangeHandler:\n options?.disableRouteChangeHandler ??\n disableRouteChangeHandler ??\n defaultRefineOptions.disableRouteChangeHandler,\n };\n\n const disableTelemetryWithDefault =\n options?.disableTelemetry ?? disableTelemetry ?? false;\n\n const reactQueryWithDefaults = {\n clientConfig:\n options?.reactQuery?.clientConfig ?? reactQueryClientConfig ?? {},\n devtoolConfig: reactQueryDevtoolConfig ?? {},\n };\n\n return {\n optionsWithDefaults,\n disableTelemetryWithDefault,\n reactQueryWithDefaults,\n };\n};\n","import type { IRefineContextOptions } from \"../../../contexts/refine/types\";\nimport type { Action } from \"../../../contexts/router/types\";\nimport type { RedirectAction } from \"../../../hooks/form/types\";\n\ntype RedirectPageProps = {\n redirectFromProps?: RedirectAction;\n action: Action;\n redirectOptions: IRefineContextOptions[\"redirect\"];\n};\n\nexport const redirectPage = ({\n redirectFromProps,\n action,\n redirectOptions,\n}: RedirectPageProps): RedirectAction => {\n if (redirectFromProps || redirectFromProps === false) {\n return redirectFromProps;\n }\n\n switch (action) {\n case \"clone\":\n return redirectOptions.afterClone;\n case \"create\":\n return redirectOptions.afterCreate;\n case \"edit\":\n return redirectOptions.afterEdit;\n default:\n return false;\n }\n};\n","type EachResolve<TResolve, Response> = (\n result: TResolve,\n index: number,\n) => Response;\ntype EachReject<TReject, Response> = (\n error: TReject,\n index: number,\n) => Response;\n\nexport const sequentialPromises = async <\n TResolve = unknown,\n TReject = unknown,\n TResolveResponse = unknown,\n TRejectResponse = unknown,\n>(\n promises: (() => Promise<TResolve>)[],\n onEachResolve: EachResolve<TResolve, TResolveResponse>,\n onEachReject: EachReject<TReject, TRejectResponse>,\n): Promise<(TResolveResponse | TRejectResponse)[]> => {\n const results = [];\n // @ts-expect-error Remove this when we enable `downLevelIterations`\n for (const [index, promise] of promises.entries()) {\n try {\n const result = await promise();\n\n results.push(onEachResolve(result, index));\n } catch (error) {\n results.push(onEachReject(error as TReject, index));\n }\n }\n return results;\n};\n","import type { IResourceItem } from \"../../../contexts/resource/types\";\n\n/**\n * Picks the resource based on the provided identifier.\n * It will first try to match based on the identifier, then the name.\n * Identifier fallbacks to `name` if `identifier` is not explicitly provided to the resource.\n */\nexport const pickResource = (\n identifier?: string,\n resources: IResourceItem[] = [],\n): IResourceItem | undefined => {\n if (!identifier) {\n return undefined;\n }\n\n let resource = resources.find((r) => r.identifier === identifier);\n if (!resource) {\n resource = resources.find((r) => r.name === identifier);\n }\n\n return resource;\n};\n","import type { IResourceItem } from \"../../../contexts/resource/types\";\nimport { pickResource } from \"../pick-resource\";\n\n/**\n * Picks the data provider name based on the provided name or fallbacks to resource definition, or `default`.\n */\nexport const pickDataProvider = (\n resourceName?: string,\n dataProviderName?: string,\n resources?: IResourceItem[],\n) => {\n if (dataProviderName) {\n return dataProviderName;\n }\n\n /**\n * In this helper, we don't do `route` based matching therefore there's no need to check for `legacy` behaviors.\n */\n const resource = pickResource(resourceName, resources);\n\n const meta = resource?.meta;\n\n if (meta?.dataProviderName) {\n return meta.dataProviderName;\n }\n\n return \"default\";\n};\n","export const handleMultiple = async <TData = unknown>(\n promises: Promise<{ data: TData }>[],\n): Promise<{ data: TData[] }> => {\n return {\n data: (await Promise.all(promises)).map((res) => res.data),\n };\n};\n","import type { GetListResponse } from \"../../../contexts/data/types\";\n\nexport const getNextPageParam = (lastPage: GetListResponse) => {\n const { pagination, cursor } = lastPage;\n\n // cursor pagination\n if (cursor?.next) {\n return cursor.next;\n }\n\n const current = pagination?.currentPage || 1;\n\n const pageSize = pagination?.pageSize || 10;\n const totalPages = Math.ceil((lastPage.total || 0) / pageSize);\n\n return current < totalPages ? Number(current) + 1 : undefined;\n};\n\nexport const getPreviousPageParam = (lastPage: GetListResponse) => {\n const { pagination, cursor } = lastPage;\n\n // cursor pagination\n if (cursor?.prev) {\n return cursor.prev;\n }\n\n const current = pagination?.currentPage || 1;\n\n return current === 1 ? undefined : current - 1;\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 { IResourceItem } from \"../../../contexts/resource/types\";\nimport type { Action } from \"../../../contexts/router/types\";\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 * - It will return an array of objects with the action, the resource and the route\n */\nexport const getActionRoutesFromResource = (\n resource: IResourceItem,\n resources: IResourceItem[],\n) => {\n const actions: ResourceActionRoute[] = [];\n\n const actionList: Action[] = [\"list\", \"show\", \"edit\", \"create\", \"clone\"];\n\n actionList.forEach((action) => {\n const route: string | undefined = resource[action];\n\n if (route) {\n actions.push({\n action,\n resource,\n route: `/${route.replace(/^\\//, \"\")}`,\n });\n }\n });\n\n return actions;\n};\n","import type { ResourceActionRoute } from \"./get-action-routes-from-resource\";\nimport { isParameter } from \"./is-parameter\";\nimport { removeLeadingTrailingSlashes } from \"./remove-leading-trailing-slashes\";\nimport { splitToSegments } from \"./split-to-segments\";\n\n/**\n * Picks the most eligible route from the given matched routes.\n * - If there's only one route, it returns it.\n * - If there's more than one route, it picks the best non-greedy match.\n */\nexport const pickMatchedRoute = (\n routes: ResourceActionRoute[],\n): ResourceActionRoute | undefined => {\n // these routes are all matched, we should pick the least parametrized one\n\n // no routes, no match\n if (routes.length === 0) {\n return undefined;\n }\n\n // no need to calculate the route segments if there's only one route\n if (routes.length === 1) {\n return routes[0];\n }\n\n // remove trailing and leading slashes\n // split them to segments\n const sanitizedRoutes = routes.map((route) => ({\n ...route,\n splitted: splitToSegments(removeLeadingTrailingSlashes(route.route)),\n }));\n\n // at this point, before calling this function, we already checked for segment lenghts and expect all of them to be the same\n const segmentsCount = sanitizedRoutes[0]?.splitted.length ?? 0;\n\n let eligibleRoutes: Array<(typeof sanitizedRoutes)[number]> = [\n ...sanitizedRoutes,\n ];\n\n // loop through the segments\n for (let i = 0; i < segmentsCount; i++) {\n const nonParametrizedRoutes = eligibleRoutes.filter(\n (route) => !isParameter(route.splitted[i]),\n );\n\n if (nonParametrizedRoutes.length === 0) {\n // keep the eligible routes as they are\n continue;\n }\n if (nonParametrizedRoutes.length === 1) {\n // no need to continue, we found the route\n eligibleRoutes = nonParametrizedRoutes;\n break;\n }\n\n // we have more than one non-parametrized route, we need to check the next segment\n eligibleRoutes = nonParametrizedRoutes;\n }\n\n return eligibleRoutes[0];\n};\n","import type { IResourceItem } from \"../../../contexts/resource/types\";\nimport type { Action } from \"../../../contexts/router/types\";\nimport { checkBySegments } from \"./check-by-segments\";\nimport { getActionRoutesFromResource } from \"./get-action-routes-from-resource\";\nimport { pickMatchedRoute } from \"./pick-matched-route\";\n\n/**\n * Match the resource from the route\n * - It will calculate all possible routes for resources and their actions\n * - It will check if the route matches any of the possible routes\n * - It will return the most eligible resource and action\n */\nexport const matchResourceFromRoute = (\n route: string,\n resources: IResourceItem[],\n): {\n found: boolean;\n resource?: IResourceItem;\n action?: Action;\n matchedRoute?: string;\n} => {\n const allActionRoutes = resources.flatMap((resource) => {\n return getActionRoutesFromResource(resource, resources);\n });\n\n const allFound = allActionRoutes.filter((actionRoute) => {\n return checkBySegments(route, actionRoute.route);\n });\n\n const mostEligible = pickMatchedRoute(allFound);\n\n return {\n found: !!mostEligible,\n resource: mostEligible?.resource,\n action: mostEligible?.action,\n matchedRoute: mostEligible?.route,\n };\n};\n","import type { IResourceItem } from \"../../../contexts/resource/types\";\n\n/**\n * Returns the parent resource of the given resource.\n * Uses the `resource.meta.parent` property.\n */\nexport const getParentResource = (\n resource: IResourceItem,\n resources: IResourceItem[],\n): IResourceItem | undefined => {\n const parentName = resource.meta?.parent;\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 { splitToSegments } from \"./split-to-segments\";\nimport { removeLeadingTrailingSlashes } from \"./remove-leading-trailing-slashes\";\nimport { isParameter } from \"./is-parameter\";\n\n/**\n * Picks the route parameters from the given route.\n * (e.g. /users/:id/posts/:postId => ['id', 'postId'])\n */\nexport const pickRouteParams = (route: string) => {\n const segments = splitToSegments(removeLeadingTrailingSlashes(route));\n\n return segments.flatMap((s) => {\n if (isParameter(s)) {\n return [s.slice(1)];\n }\n\n return [];\n });\n};\n","/**\n * Prepares the route params by checking the existing params and meta data.\n * Meta data is prioritized over params.\n * Params are prioritized over predetermined id, action and resource.\n * This means, we can use `meta` for user supplied params (both manually or from the query string)\n */\nexport const prepareRouteParams = <\n TRouteParams extends Record<string, unknown> = Record<string, unknown>,\n>(\n routeParams: (keyof TRouteParams)[],\n meta: Record<string, unknown> = {},\n): Partial<TRouteParams> => {\n return routeParams.reduce(\n (acc, key) => {\n const value = meta[key as string];\n if (typeof value !== \"undefined\") {\n acc[key] = value as TRouteParams[keyof TRouteParams];\n }\n return acc;\n },\n {} as Partial<TRouteParams>,\n );\n};\n","import type { MetaQuery } from \"../../../contexts/data/types\";\nimport type { ParseResponse } from \"../../../contexts/router/types\";\nimport { pickRouteParams } from \"./pick-route-params\";\nimport { prepareRouteParams } from \"./prepare-route-params\";\n\n/**\n * This function will compose a route with the given params and meta.\n * - A route can have parameters like (eg: /users/:id)\n * - First we pick the route params from the route (eg: [id])\n * - Then we prepare the route params with the given params and meta (eg: { id: 1 })\n * - Then we replace the route params with the prepared route params (eg: /users/1)\n */\nexport const composeRoute = (\n designatedRoute: string,\n resourceMeta: MetaQuery = {},\n parsed: ParseResponse = {},\n meta: Record<string, unknown> = {},\n): string => {\n // pickRouteParams (from the route)\n const routeParams = pickRouteParams(designatedRoute);\n // prepareRouteParams (from route params, params and meta)\n const preparedRouteParams = prepareRouteParams(routeParams, {\n ...resourceMeta,\n ...(typeof parsed?.id !== \"undefined\" ? { id: parsed.id } : {}),\n ...(typeof parsed?.action !== \"undefined\" ? { action: parsed.action } : {}),\n ...(typeof parsed?.resource !== \"undefined\"\n ? { resource: parsed.resource }\n : {}),\n ...parsed?.params,\n ...meta,\n });\n // replace route params with prepared route params\n return designatedRoute.replace(/:([^\\/]+)/g, (match, key) => {\n const fromParams = preparedRouteParams[key];\n if (typeof fromParams !== \"undefined\") {\n return `${fromParams}`;\n }\n return match;\n });\n};\n","import { useAuthProviderContext } from \"@contexts/auth\";\n\n/**\n * @returns authProvider if provided, otherwise null\n * @internal\n */\nexport const useActiveAuthProvider = () => {\n const authProvider = useAuthProviderContext();\n\n if (authProvider.isProvided) {\n return authProvider;\n }\n\n return null;\n};\n","import type { Pagination } from \"../../../contexts/data/types\";\n\ntype HandlePaginationParamsProps = {\n pagination?: Pagination;\n};\n\nexport const handlePaginationParams = ({\n pagination,\n}: HandlePaginationParamsProps = {}): Required<Pagination> => {\n const mode = pagination?.mode ?? \"server\";\n\n const currentPage = pagination?.currentPage ?? 1;\n\n const pageSize = pagination?.pageSize ?? 10;\n\n return {\n currentPage,\n pageSize,\n mode,\n };\n};\n","import { useState, useEffect } from \"react\";\n\nexport const useMediaQuery = (query: string) => {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n const media = window.matchMedia(query);\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = () => setMatches(media.matches);\n window.addEventListener(\"resize\", listener);\n return () => window.removeEventListener(\"resize\", listener);\n }, [matches, query]);\n\n return matches;\n};\n","import type { useTranslate } from \"../../../hooks/i18n\";\n\nexport const safeTranslate = (\n translate: ReturnType<typeof useTranslate>,\n key: string,\n defaultMessage?: string,\n options?: any,\n) => {\n const translated = options\n ? translate(key, options, defaultMessage)\n : translate(key, defaultMessage);\n\n const fallback = defaultMessage ?? key;\n\n if (translated === key || typeof translated === \"undefined\") {\n return fallback;\n }\n\n return translated;\n};\n","import { useContext } from \"react\";\n\nimport { RefineContext } from \"@contexts/refine\";\nimport type { IRefineContextOptions } from \"../../contexts/refine/types\";\nimport type { MutationMode } from \"../../contexts/data/types\";\n\ntype UseMutationModeType = (\n preferredMutationMode?: MutationMode,\n preferredUndoableTimeout?: number,\n) => {\n mutationMode: IRefineContextOptions[\"mutationMode\"];\n undoableTimeout: IRefineContextOptions[\"undoableTimeout\"];\n};\n\n/**\n * Mutation mode determines which mode the mutation runs with.\n * Mutations can run under three different modes: `pessimistic`, `optimistic` and `undoable`.\n