@refinedev/core 4.23.0 → 4.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/dist/contexts/refine/IRefineContext.d.ts +3 -1
  3. package/dist/contexts/refine/IRefineContext.d.ts.map +1 -1
  4. package/dist/contexts/refine/index.d.ts.map +1 -1
  5. package/dist/definitions/helpers/generateDocumentTitle/index.d.ts +1 -1
  6. package/dist/definitions/helpers/generateDocumentTitle/index.d.ts.map +1 -1
  7. package/dist/definitions/helpers/handleRefineOptions/index.d.ts.map +1 -1
  8. package/dist/definitions/helpers/index.d.ts +1 -0
  9. package/dist/definitions/helpers/index.d.ts.map +1 -1
  10. package/dist/definitions/helpers/sanitize-resource/index.d.ts +2 -2
  11. package/dist/definitions/helpers/sanitize-resource/index.d.ts.map +1 -1
  12. package/dist/definitions/helpers/useUserFriendlyName/index.d.ts +6 -0
  13. package/dist/definitions/helpers/useUserFriendlyName/index.d.ts.map +1 -0
  14. package/dist/definitions/helpers/userFriendlyResourceName/index.d.ts +1 -0
  15. package/dist/definitions/helpers/userFriendlyResourceName/index.d.ts.map +1 -1
  16. package/dist/esm/index.js +6 -6
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/hooks/accessControl/useCan/index.d.ts.map +1 -1
  19. package/dist/hooks/breadcrumb/index.d.ts.map +1 -1
  20. package/dist/hooks/data/useCreate.d.ts.map +1 -1
  21. package/dist/hooks/data/useCreateMany.d.ts.map +1 -1
  22. package/dist/hooks/data/useDelete.d.ts.map +1 -1
  23. package/dist/hooks/data/useDeleteMany.d.ts.map +1 -1
  24. package/dist/hooks/data/useUpdate.d.ts.map +1 -1
  25. package/dist/hooks/data/useUpdateMany.d.ts.map +1 -1
  26. package/dist/hooks/export/index.d.ts.map +1 -1
  27. package/dist/hooks/menu/useMenu.d.ts.map +1 -1
  28. package/dist/hooks/useMeta/index.d.ts +0 -13
  29. package/dist/hooks/useMeta/index.d.ts.map +1 -1
  30. package/dist/iife/index.js +6 -6
  31. package/dist/iife/index.js.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +6 -6
  35. package/dist/index.js.map +1 -1
  36. package/dist/interfaces/index.d.ts +1 -0
  37. package/dist/interfaces/index.d.ts.map +1 -1
  38. package/dist/interfaces/textTransformers.d.ts +21 -0
  39. package/dist/interfaces/textTransformers.d.ts.map +1 -0
  40. package/package.json +1 -1
  41. package/src/contexts/refine/IRefineContext.ts +3 -0
  42. package/src/contexts/refine/index.tsx +7 -0
  43. package/src/definitions/helpers/generateDocumentTitle/index.ts +8 -8
  44. package/src/definitions/helpers/handleRefineOptions/index.ts +11 -0
  45. package/src/definitions/helpers/index.ts +1 -0
  46. package/src/definitions/helpers/sanitize-resource/index.ts +9 -2
  47. package/src/definitions/helpers/useUserFriendlyName/index.ts +24 -0
  48. package/src/definitions/helpers/userFriendlyResourceName/index.ts +1 -0
  49. package/src/hooks/accessControl/useCan/index.ts +6 -3
  50. package/src/hooks/breadcrumb/index.ts +11 -7
  51. package/src/hooks/data/useCreate.ts +6 -3
  52. package/src/hooks/data/useCreateMany.ts +5 -2
  53. package/src/hooks/data/useDelete.ts +7 -3
  54. package/src/hooks/data/useDeleteMany.ts +6 -2
  55. package/src/hooks/data/useUpdate.ts +7 -3
  56. package/src/hooks/data/useUpdateMany.ts +7 -3
  57. package/src/hooks/export/index.ts +3 -2
  58. package/src/hooks/menu/useMenu.tsx +3 -2
  59. package/src/hooks/useMeta/index.ts +1 -1
  60. package/src/index.tsx +1 -0
  61. package/src/interfaces/index.ts +2 -0
  62. package/src/interfaces/textTransformers.ts +20 -0
@@ -46,4 +46,5 @@ export * from "./form-url-params";
46
46
  export * from "./auth";
47
47
  export * from "./bindings";
48
48
  export * from "./prettify";
49
+ export * from "./textTransformers";
49
50
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,0CAA0C,CAAC;AACzD,cAAc,iDAAiD,CAAC;AAChE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AAEtD,cAAc,2BAA2B,CAAC;AAG1C,cAAc,WAAW,CAAC;AAG1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,UAAU,CAAC;AAGzB,cAAc,oBAAoB,CAAC;AAGnC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,aAAa,CAAC;AAG5B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,YAAY,CAAC;AAG3B,cAAc,YAAY,CAAC;AAG3B,cAAc,QAAQ,CAAC;AAGvB,cAAc,YAAY,CAAC;AAE3B,oBAAY,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AACtC,oBAAY,UAAU,GAAG;IACrB,EAAE,CAAC,EAAE,OAAO,CAAC;IAEb,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB,CAAC;AACF,MAAM,WAAW,MAAM;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACjB;AAGD,oBAAY,SAAS,GAAG,aAAa,GAAG;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,EAAE,CAAC;CACzB,CAAC;AAEF,oBAAY,SAAS,GAAG,aAAa,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,cAAc,mBAAmB,CAAC;AAElC,cAAc,QAAQ,CAAC;AAEvB,cAAc,YAAY,CAAC;AAE3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,0CAA0C,CAAC;AACzD,cAAc,iDAAiD,CAAC;AAChE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AAEtD,cAAc,2BAA2B,CAAC;AAG1C,cAAc,WAAW,CAAC;AAG1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,UAAU,CAAC;AAGzB,cAAc,oBAAoB,CAAC;AAGnC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,aAAa,CAAC;AAG5B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,YAAY,CAAC;AAG3B,cAAc,YAAY,CAAC;AAG3B,cAAc,QAAQ,CAAC;AAGvB,cAAc,YAAY,CAAC;AAE3B,oBAAY,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AACtC,oBAAY,UAAU,GAAG;IACrB,EAAE,CAAC,EAAE,OAAO,CAAC;IAEb,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB,CAAC;AACF,MAAM,WAAW,MAAM;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACjB;AAGD,oBAAY,SAAS,GAAG,aAAa,GAAG;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,EAAE,CAAC;CACzB,CAAC;AAEF,oBAAY,SAAS,GAAG,aAAa,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,cAAc,mBAAmB,CAAC;AAElC,cAAc,QAAQ,CAAC;AAEvB,cAAc,YAAY,CAAC;AAE3B,cAAc,YAAY,CAAC;AAE3B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,21 @@
1
+ export declare type TextTransformers = {
2
+ /**
3
+ * Convert a camelized/dasherized/underscored string into a humanized one
4
+ * @example
5
+ * humanize("some_name") => "Some name"
6
+ */
7
+ humanize?: (text: string) => string;
8
+ /**
9
+ * Pluralize a word
10
+ * @example
11
+ * plural('regex') => "regexes"
12
+ */
13
+ plural?: (word: string) => string;
14
+ /**
15
+ * Singularize a word
16
+ * @example
17
+ * singular('singles') => "single"
18
+ */
19
+ singular?: (word: string) => string;
20
+ };
21
+ //# sourceMappingURL=textTransformers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textTransformers.d.ts","sourceRoot":"","sources":["../../src/interfaces/textTransformers.ts"],"names":[],"mappings":"AAAA,oBAAY,gBAAgB,GAAG;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refinedev/core",
3
- "version": "4.23.0",
3
+ "version": "4.25.0",
4
4
  "description": "refine is a React-based framework for building internal tools, rapidly. It ships with Ant Design System, an enterprise-level UI toolkit.",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -9,6 +9,7 @@ import {
9
9
  LayoutProps,
10
10
  LiveModeProps,
11
11
  RedirectAction,
12
+ TextTransformers,
12
13
  } from "../../interfaces";
13
14
  import { UseLoadingOvertimeRefineContext } from "../../hooks/useLoadingOvertime";
14
15
 
@@ -30,6 +31,7 @@ export interface IRefineOptions {
30
31
  devtoolConfig?: React.ComponentProps<typeof ReactQueryDevtools> | false;
31
32
  };
32
33
  overtime?: UseLoadingOvertimeRefineContext;
34
+ textTransformers?: TextTransformers;
33
35
  }
34
36
 
35
37
  export interface IRefineContextOptions {
@@ -45,6 +47,7 @@ export interface IRefineContextOptions {
45
47
  afterEdit: RedirectAction;
46
48
  };
47
49
  overtime: UseLoadingOvertimeRefineContext;
50
+ textTransformers: Required<TextTransformers>;
48
51
  }
49
52
 
50
53
  export interface IRefineContext {
@@ -1,4 +1,6 @@
1
1
  import React from "react";
2
+ import pluralize from "pluralize";
3
+ import { humanizeString } from "../../definitions/helpers/humanizeString";
2
4
 
3
5
  import {
4
6
  IRefineContextOptions,
@@ -23,6 +25,11 @@ export const defaultRefineOptions: IRefineContextOptions = {
23
25
  overtime: {
24
26
  interval: 1000,
25
27
  },
28
+ textTransformers: {
29
+ humanize: humanizeString,
30
+ plural: pluralize.plural,
31
+ singular: pluralize.singular,
32
+ },
26
33
  };
27
34
 
28
35
  export const RefineContext = React.createContext<IRefineContext>({
@@ -1,5 +1,4 @@
1
1
  import { IResourceItem } from "@contexts/resource";
2
- import capitalize from "lodash/capitalize";
3
2
  import { userFriendlyResourceName } from "../userFriendlyResourceName";
4
3
 
5
4
  /**
@@ -17,6 +16,7 @@ export function generateDefaultDocumentTitle(
17
16
  resource?: IResourceItem,
18
17
  action?: string,
19
18
  id?: string,
19
+ resourceName?: string,
20
20
  ) {
21
21
  const actionPrefixMatcher = {
22
22
  create: "Create new ",
@@ -28,16 +28,16 @@ export function generateDefaultDocumentTitle(
28
28
 
29
29
  const identifier = resource?.identifier ?? resource?.name;
30
30
 
31
- const resourceName =
31
+ const resourceNameFallback =
32
32
  resource?.label ??
33
33
  resource?.meta?.label ??
34
- capitalize(
35
- userFriendlyResourceName(
36
- identifier,
37
- action === "list" ? "plural" : "singular",
38
- ),
34
+ userFriendlyResourceName(
35
+ identifier,
36
+ action === "list" ? "plural" : "singular",
39
37
  );
40
38
 
39
+ const resourceNameWithFallback = resourceName ?? resourceNameFallback;
40
+
41
41
  const defaultTitle = translate("documentTitle.default", "refine");
42
42
  const suffix = translate("documentTitle.suffix", " | refine");
43
43
  let autoGeneratedTitle = defaultTitle;
@@ -50,7 +50,7 @@ export function generateDefaultDocumentTitle(
50
50
  actionPrefixMatcher[
51
51
  action as keyof typeof actionPrefixMatcher
52
52
  ] ?? ""
53
- }${resourceName}${suffix}`,
53
+ }${resourceNameWithFallback}${suffix}`,
54
54
  );
55
55
  }
56
56
 
@@ -75,6 +75,17 @@ export const handleRefineOptions = ({
75
75
  defaultRefineOptions.redirect.afterEdit,
76
76
  },
77
77
  overtime: options?.overtime ?? defaultRefineOptions.overtime,
78
+ textTransformers: {
79
+ humanize:
80
+ options?.textTransformers?.humanize ??
81
+ defaultRefineOptions.textTransformers.humanize,
82
+ plural:
83
+ options?.textTransformers?.plural ??
84
+ defaultRefineOptions.textTransformers.plural,
85
+ singular:
86
+ options?.textTransformers?.singular ??
87
+ defaultRefineOptions.textTransformers.singular,
88
+ },
78
89
  };
79
90
 
80
91
  const disableTelemetryWithDefault =
@@ -25,3 +25,4 @@ export { useActiveAuthProvider } from "./useActiveAuthProvider";
25
25
  export { handlePaginationParams } from "./handlePaginationParams";
26
26
  export { useMediaQuery } from "./useMediaQuery";
27
27
  export { generateDefaultDocumentTitle } from "./generateDocumentTitle";
28
+ export { useUserFriendlyName } from "./useUserFriendlyName";
@@ -4,8 +4,15 @@ import { IResourceItem } from "../../../interfaces/bindings/resource";
4
4
  * Remove all properties that are non-serializable from a resource object.
5
5
  */
6
6
  export const sanitizeResource = (
7
- resource: Partial<IResourceItem> & { children?: unknown },
8
- ): Partial<IResourceItem> => {
7
+ resource?: Partial<IResourceItem> &
8
+ Required<Pick<IResourceItem, "name">> & { children?: unknown },
9
+ ):
10
+ | (Partial<IResourceItem> & Required<Pick<IResourceItem, "name">>)
11
+ | undefined => {
12
+ if (!resource) {
13
+ return undefined;
14
+ }
15
+
9
16
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
17
  const {
11
18
  icon,
@@ -0,0 +1,24 @@
1
+ import { useRefineContext } from "@hooks/refine";
2
+
3
+ /**
4
+ * A method that the internal uses
5
+ * @internal
6
+ */
7
+ export const useUserFriendlyName = () => {
8
+ const {
9
+ options: { textTransformers },
10
+ } = useRefineContext();
11
+
12
+ const getFriendlyName = (
13
+ name = "",
14
+ type: "singular" | "plural",
15
+ ): string => {
16
+ const humanizeName = textTransformers.humanize(name);
17
+ if (type === "singular") {
18
+ return textTransformers.singular(humanizeName);
19
+ }
20
+ return textTransformers.plural(humanizeName);
21
+ };
22
+
23
+ return getFriendlyName;
24
+ };
@@ -4,6 +4,7 @@ import { humanizeString } from "@definitions";
4
4
  /**
5
5
  * A method that the internal uses
6
6
  * @internal
7
+ * @deprecated use `useUserFriendlyName` instead.
7
8
  */
8
9
  export const userFriendlyResourceName = (
9
10
  resource = "",
@@ -39,7 +39,7 @@ export const useCan = ({
39
39
  const { resource: _resource, ...paramsRest } = params ?? {};
40
40
 
41
41
  /* eslint-disable @typescript-eslint/no-unused-vars */
42
- const sanitizedResource = sanitizeResource(_resource ?? {});
42
+ const sanitizedResource = sanitizeResource(_resource);
43
43
 
44
44
  /* eslint-enable @typescript-eslint/no-unused-vars */
45
45
  const queryResponse = useQuery<CanReturnType>(
@@ -54,8 +54,11 @@ export const useCan = ({
54
54
  ],
55
55
  // Enabled check for `can` is enough to be sure that it's defined in the query function but TS is not smart enough to know that.
56
56
  () =>
57
- can?.({ action, resource, params: paramsRest }) ??
58
- Promise.resolve({ can: true }),
57
+ can?.({
58
+ action,
59
+ resource,
60
+ params: { ...paramsRest, resource: sanitizedResource },
61
+ }) ?? Promise.resolve({ can: true }),
59
62
  {
60
63
  enabled: typeof can !== "undefined",
61
64
  ...queryOptions,
@@ -1,9 +1,9 @@
1
1
  import React, { useContext } from "react";
2
2
  import warnOnce from "warn-once";
3
3
 
4
- import { useResource, useTranslate } from "@hooks";
4
+ import { useRefineContext, useResource, useTranslate } from "@hooks";
5
5
  import { TranslationContext } from "@contexts/translation";
6
- import { humanizeString, pickNotDeprecated } from "@definitions";
6
+ import { pickNotDeprecated } from "@definitions";
7
7
 
8
8
  import { IResourceItem } from "../../interfaces";
9
9
  import { useRouterType } from "@contexts/router-picker";
@@ -35,10 +35,11 @@ export const useBreadcrumb = ({
35
35
  const routerType = useRouterType();
36
36
  const { i18nProvider } = useContext(TranslationContext);
37
37
  const parsed = useParsed();
38
-
39
38
  const translate = useTranslate();
40
-
41
39
  const { resources, resource, action } = useResource();
40
+ const {
41
+ options: { textTransformers },
42
+ } = useRefineContext();
42
43
 
43
44
  const breadcrumbs: BreadcrumbsType[] = [];
44
45
 
@@ -93,7 +94,7 @@ export const useBreadcrumb = ({
93
94
  ) ??
94
95
  translate(
95
96
  `${parentResource.name}.${parentResource.name}`,
96
- humanizeString(parentResource.name),
97
+ textTransformers.humanize(parentResource.name),
97
98
  ),
98
99
  href: href,
99
100
  icon: pickNotDeprecated(
@@ -116,11 +117,14 @@ export const useBreadcrumb = ({
116
117
  `[useBreadcrumb]: Breadcrumb missing translate key for the "${action}" action. Please add "actions.${action}" key to your translation file.\nFor more information, see https://refine.dev/docs/api-reference/core/hooks/useBreadcrumb/#i18n-support`,
117
118
  );
118
119
  breadcrumbs.push({
119
- label: translate(`buttons.${action}`, humanizeString(action)),
120
+ label: translate(
121
+ `buttons.${action}`,
122
+ textTransformers.humanize(action),
123
+ ),
120
124
  });
121
125
  } else {
122
126
  breadcrumbs.push({
123
- label: translate(key, humanizeString(action)),
127
+ label: translate(key, textTransformers.humanize(action)),
124
128
  });
125
129
  }
126
130
  }
@@ -3,7 +3,6 @@ import {
3
3
  UseMutationOptions,
4
4
  UseMutationResult,
5
5
  } from "@tanstack/react-query";
6
- import pluralize from "pluralize";
7
6
  import {
8
7
  pickDataProvider,
9
8
  pickNotDeprecated,
@@ -28,6 +27,7 @@ import {
28
27
  useInvalidate,
29
28
  useOnError,
30
29
  useMeta,
30
+ useRefineContext,
31
31
  } from "@hooks";
32
32
  import {
33
33
  useLoadingOvertime,
@@ -128,6 +128,9 @@ export const useCreate = <
128
128
  const { log } = useLog();
129
129
  const handleNotification = useHandleNotification();
130
130
  const getMeta = useMeta();
131
+ const {
132
+ options: { textTransformers },
133
+ } = useRefineContext();
131
134
 
132
135
  const mutation = useMutation<
133
136
  CreateResponse<TData>,
@@ -173,7 +176,7 @@ export const useCreate = <
173
176
  ) => {
174
177
  const { resource, identifier } = select(resourceName);
175
178
 
176
- const resourceSingular = pluralize.singular(identifier);
179
+ const resourceSingular = textTransformers.singular(identifier);
177
180
 
178
181
  const notificationConfig =
179
182
  typeof successNotificationFromProp === "function"
@@ -250,7 +253,7 @@ export const useCreate = <
250
253
 
251
254
  const { identifier } = select(resourceName);
252
255
 
253
- const resourceSingular = pluralize.singular(identifier);
256
+ const resourceSingular = textTransformers.singular(identifier);
254
257
 
255
258
  const notificationConfig =
256
259
  typeof errorNotificationFromProp === "function"
@@ -3,7 +3,6 @@ import {
3
3
  UseMutationOptions,
4
4
  UseMutationResult,
5
5
  } from "@tanstack/react-query";
6
- import pluralize from "pluralize";
7
6
 
8
7
  import {
9
8
  BaseRecord,
@@ -22,6 +21,7 @@ import {
22
21
  useInvalidate,
23
22
  useLog,
24
23
  useMeta,
24
+ useRefineContext,
25
25
  } from "@hooks";
26
26
  import {
27
27
  handleMultiple,
@@ -102,6 +102,9 @@ export const useCreateMany = <
102
102
  const invalidateStore = useInvalidate();
103
103
  const { log } = useLog();
104
104
  const getMeta = useMeta();
105
+ const {
106
+ options: { textTransformers },
107
+ } = useRefineContext();
105
108
 
106
109
  const mutation = useMutation<
107
110
  CreateManyResponse<TData>,
@@ -161,7 +164,7 @@ export const useCreateMany = <
161
164
  ) => {
162
165
  const { resource, identifier } = select(resourceName);
163
166
 
164
- const resourcePlural = pluralize.plural(identifier);
167
+ const resourcePlural = textTransformers.plural(identifier);
165
168
 
166
169
  const notificationConfig =
167
170
  typeof successNotification === "function"
@@ -4,7 +4,6 @@ import {
4
4
  UseMutationResult,
5
5
  UseMutationOptions,
6
6
  } from "@tanstack/react-query";
7
- import pluralize from "pluralize";
8
7
 
9
8
  import {
10
9
  useResource,
@@ -18,6 +17,7 @@ import {
18
17
  useInvalidate,
19
18
  useOnError,
20
19
  useMeta,
20
+ useRefineContext,
21
21
  } from "@hooks";
22
22
  import { ActionTypes } from "@contexts/undoableQueue";
23
23
  import {
@@ -134,6 +134,9 @@ export const useDelete = <
134
134
  const handleNotification = useHandleNotification();
135
135
  const invalidateStore = useInvalidate();
136
136
  const getMeta = useMeta();
137
+ const {
138
+ options: { textTransformers },
139
+ } = useRefineContext();
137
140
 
138
141
  const mutation = useMutation<
139
142
  DeleteOneResponse<TData>,
@@ -343,7 +346,7 @@ export const useDelete = <
343
346
  ) => {
344
347
  const { resource, identifier } = select(resourceName);
345
348
 
346
- const resourceSingular = pluralize.singular(identifier);
349
+ const resourceSingular = textTransformers.singular(identifier);
347
350
 
348
351
  // Remove the queries from the cache:
349
352
  queryClient.removeQueries(context?.queryKey.detail(id));
@@ -420,7 +423,8 @@ export const useDelete = <
420
423
  if (err.message !== "mutationCancelled") {
421
424
  checkError(err);
422
425
 
423
- const resourceSingular = pluralize.singular(identifier);
426
+ const resourceSingular =
427
+ textTransformers.singular(identifier);
424
428
 
425
429
  const notificationConfig =
426
430
  typeof errorNotification === "function"
@@ -4,7 +4,6 @@ import {
4
4
  UseMutationResult,
5
5
  UseMutationOptions,
6
6
  } from "@tanstack/react-query";
7
- import pluralize from "pluralize";
8
7
 
9
8
  import {
10
9
  DeleteManyResponse,
@@ -31,6 +30,7 @@ import {
31
30
  useLog,
32
31
  useOnError,
33
32
  useMeta,
33
+ useRefineContext,
34
34
  } from "@hooks";
35
35
  import { ActionTypes } from "@contexts/undoableQueue";
36
36
  import {
@@ -133,6 +133,9 @@ export const useDeleteMany = <
133
133
  const { resources, select } = useResource();
134
134
  const queryClient = useQueryClient();
135
135
  const getMeta = useMeta();
136
+ const {
137
+ options: { textTransformers },
138
+ } = useRefineContext();
136
139
 
137
140
  const mutation = useMutation<
138
141
  DeleteManyResponse<TData>,
@@ -448,7 +451,8 @@ export const useDeleteMany = <
448
451
 
449
452
  if (err.message !== "mutationCancelled") {
450
453
  checkError(err);
451
- const resourceSingular = pluralize.singular(identifier);
454
+ const resourceSingular =
455
+ textTransformers.singular(identifier);
452
456
 
453
457
  const notificationConfig =
454
458
  typeof errorNotification === "function"
@@ -19,7 +19,6 @@ import {
19
19
  GetListResponse,
20
20
  IQueryKeys,
21
21
  } from "../../interfaces";
22
- import pluralize from "pluralize";
23
22
  import {
24
23
  useResource,
25
24
  useMutationMode,
@@ -32,6 +31,7 @@ import {
32
31
  useInvalidate,
33
32
  useOnError,
34
33
  useMeta,
34
+ useRefineContext,
35
35
  } from "@hooks";
36
36
  import {
37
37
  queryKeys,
@@ -165,6 +165,9 @@ export const useUpdate = <
165
165
  const handleNotification = useHandleNotification();
166
166
  const invalidateStore = useInvalidate();
167
167
  const getMeta = useMeta();
168
+ const {
169
+ options: { textTransformers },
170
+ } = useRefineContext();
168
171
 
169
172
  const mutation = useMutation<
170
173
  UpdateResponse<TData>,
@@ -401,7 +404,7 @@ export const useUpdate = <
401
404
  ) => {
402
405
  const { resource, identifier } = select(resourceName);
403
406
 
404
- const resourceSingular = pluralize.singular(identifier);
407
+ const resourceSingular = textTransformers.singular(identifier);
405
408
 
406
409
  const notificationConfig =
407
410
  typeof successNotification === "function"
@@ -487,7 +490,8 @@ export const useUpdate = <
487
490
  if (err.message !== "mutationCancelled") {
488
491
  checkError?.(err);
489
492
 
490
- const resourceSingular = pluralize.singular(identifier);
493
+ const resourceSingular =
494
+ textTransformers.singular(identifier);
491
495
 
492
496
  const notificationConfig =
493
497
  typeof errorNotification === "function"
@@ -4,7 +4,6 @@ import {
4
4
  UseMutationResult,
5
5
  useQueryClient,
6
6
  } from "@tanstack/react-query";
7
- import pluralize from "pluralize";
8
7
 
9
8
  import {
10
9
  useResource,
@@ -18,6 +17,7 @@ import {
18
17
  useLog,
19
18
  useOnError,
20
19
  useMeta,
20
+ useRefineContext,
21
21
  } from "@hooks";
22
22
  import { ActionTypes } from "@contexts/undoableQueue";
23
23
  import {
@@ -140,6 +140,9 @@ export const useUpdateMany = <
140
140
  const invalidateStore = useInvalidate();
141
141
  const { log } = useLog();
142
142
  const getMeta = useMeta();
143
+ const {
144
+ options: { textTransformers },
145
+ } = useRefineContext();
143
146
 
144
147
  const mutation = useMutation<
145
148
  UpdateManyResponse<TData>,
@@ -406,7 +409,7 @@ export const useUpdateMany = <
406
409
  ) => {
407
410
  const { resource, identifier } = select(resourceName);
408
411
 
409
- const resourceSingular = pluralize.singular(identifier);
412
+ const resourceSingular = textTransformers.singular(identifier);
410
413
 
411
414
  const notificationConfig =
412
415
  typeof successNotification === "function"
@@ -501,7 +504,8 @@ export const useUpdateMany = <
501
504
  if (err.message !== "mutationCancelled") {
502
505
  checkError?.(err);
503
506
 
504
- const resourceSingular = pluralize.singular(identifier);
507
+ const resourceSingular =
508
+ textTransformers.singular(identifier);
505
509
 
506
510
  const notificationConfig =
507
511
  typeof errorNotification === "function"
@@ -8,7 +8,7 @@ import {
8
8
  MetaQuery,
9
9
  } from "../../interfaces";
10
10
  import {
11
- userFriendlyResourceName,
11
+ useUserFriendlyName,
12
12
  pickDataProvider,
13
13
  pickNotDeprecated,
14
14
  } from "@definitions";
@@ -114,8 +114,9 @@ export const useExport = <
114
114
  const { resource, resources, identifier } = useResource(
115
115
  pickNotDeprecated(resourceFromProps, resourceName),
116
116
  );
117
+ const getFriendlyName = useUserFriendlyName();
117
118
 
118
- const filename = `${userFriendlyResourceName(
119
+ const filename = `${getFriendlyName(
119
120
  identifier,
120
121
  "plural",
121
122
  )}-${new Date().toLocaleString()}`;
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { useTranslate, useResource, useParsed, useRouterContext } from "..";
3
- import { userFriendlyResourceName, pickNotDeprecated } from "@definitions";
3
+ import { useUserFriendlyName, pickNotDeprecated } from "@definitions";
4
4
  import { useRouterType } from "../../contexts/router-picker";
5
5
  import { createResourceKey } from "../../definitions/helpers/menu/create-resource-key";
6
6
  import { useGetToPath } from "../router/use-get-to-path/index";
@@ -56,6 +56,7 @@ export const useMenu = (
56
56
  const { pathname } = useParsed();
57
57
  const { useLocation } = useRouterContext();
58
58
  const { pathname: legacyPath } = useLocation();
59
+ const getFriendlyName = useUserFriendlyName();
59
60
 
60
61
  const cleanPathname =
61
62
  routerType === "legacy"
@@ -117,7 +118,7 @@ export const useMenu = (
117
118
  ) ??
118
119
  translate(
119
120
  `${item.name}.${item.name}`,
120
- userFriendlyResourceName(item.name, "plural"),
121
+ getFriendlyName(item.name, "plural"),
121
122
  ),
122
123
  };
123
124
  },
@@ -17,7 +17,7 @@ export const useMeta = () => {
17
17
  resource?: IResourceItem;
18
18
  meta?: MetaQuery;
19
19
  } = {}) => {
20
- const { meta } = sanitizeResource(resource ?? {});
20
+ const { meta } = sanitizeResource(resource) ?? { meta: {} };
21
21
 
22
22
  // this fields came from the query params and should be removed from the meta because they are not part of the meta.
23
23
  const {
package/src/index.tsx CHANGED
@@ -114,6 +114,7 @@ export {
114
114
  legacyResourceTransform,
115
115
  matchResourceFromRoute,
116
116
  useActiveAuthProvider,
117
+ useUserFriendlyName,
117
118
  } from "./definitions/helpers";
118
119
  export { file2Base64 } from "./definitions/upload";
119
120
  export { generateDefaultDocumentTitle } from "./definitions";
@@ -84,3 +84,5 @@ export * from "./auth";
84
84
  export * from "./bindings";
85
85
 
86
86
  export * from "./prettify";
87
+
88
+ export * from "./textTransformers";
@@ -0,0 +1,20 @@
1
+ export type TextTransformers = {
2
+ /**
3
+ * Convert a camelized/dasherized/underscored string into a humanized one
4
+ * @example
5
+ * humanize("some_name") => "Some name"
6
+ */
7
+ humanize?: (text: string) => string;
8
+ /**
9
+ * Pluralize a word
10
+ * @example
11
+ * plural('regex') => "regexes"
12
+ */
13
+ plural?: (word: string) => string;
14
+ /**
15
+ * Singularize a word
16
+ * @example
17
+ * singular('singles') => "single"
18
+ */
19
+ singular?: (word: string) => string;
20
+ };