@refinedev/core 4.1.6 → 4.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refinedev/core",
3
- "version": "4.1.6",
3
+ "version": "4.2.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",
@@ -1,9 +1,39 @@
1
1
  import React from "react";
2
2
 
3
- import { useCan } from "@hooks";
4
- import { CanParams } from "../../interfaces";
3
+ import {
4
+ useCan,
5
+ useParsed,
6
+ useResource,
7
+ useResourceWithRoute,
8
+ useRouterContext,
9
+ useRouterType,
10
+ } from "@hooks";
11
+ import {
12
+ BaseKey,
13
+ IResourceItem,
14
+ ITreeMenu,
15
+ ResourceRouterParams,
16
+ } from "../../interfaces";
17
+ import { pickResource } from "@definitions/helpers/pick-resource";
5
18
 
6
- export type CanAccessProps = CanParams & {
19
+ type CanAccessBaseProps = {
20
+ /**
21
+ * Resource name for API data interactions
22
+ */
23
+ resource?: string;
24
+ /**
25
+ * Intended action on resource
26
+ */
27
+ action: string;
28
+ /**
29
+ * Parameters associated with the resource
30
+ * @type { resource?: [IResourceItem](https://refine.dev/docs/api-reference/core/interfaceReferences/#canparams), id?: [BaseKey](https://refine.dev/docs/api-reference/core/interfaceReferences/#basekey), [key: string]: any }
31
+ */
32
+ params?: {
33
+ resource?: IResourceItem & { children?: ITreeMenu[] };
34
+ id?: BaseKey;
35
+ [key: string]: any;
36
+ };
7
37
  /**
8
38
  * Content to show if access control returns `false`
9
39
  */
@@ -11,18 +41,112 @@ export type CanAccessProps = CanParams & {
11
41
  children: React.ReactNode;
12
42
  };
13
43
 
44
+ type CanAccessWithoutParamsProps = {
45
+ [key in Exclude<
46
+ keyof CanAccessBaseProps,
47
+ "fallback" | "children"
48
+ >]?: undefined;
49
+ } & {
50
+ [key in "fallback" | "children"]?: CanAccessBaseProps[key];
51
+ };
52
+
53
+ export type CanAccessProps = CanAccessBaseProps | CanAccessWithoutParamsProps;
54
+
14
55
  export const CanAccess: React.FC<CanAccessProps> = ({
15
- resource,
56
+ resource: resourceFromProp,
16
57
  action,
17
58
  params,
18
59
  fallback,
19
60
  children,
20
61
  ...rest
21
62
  }) => {
63
+ const routerType = useRouterType();
64
+ const { resources } = useResource();
65
+ const { useParams } = useRouterContext();
66
+ const {
67
+ resource: resourceFromRouter,
68
+ id: idFromRouter,
69
+ action: actionFromRouter,
70
+ } = useParsed();
71
+
72
+ const {
73
+ resource: legacyResourceFromRoute,
74
+ id: legacyIdFromParams,
75
+ action: legacyActionFromParams,
76
+ } = useParams<ResourceRouterParams>();
77
+
78
+ const newResourceNameFromRouter = resourceFromRouter?.name;
79
+
80
+ /** We only accept `id` from URL params if `resource` is not explicitly passed. */
81
+ /** This is done to avoid sending wrong requests for custom `resource` and an async `id` */
82
+ const defaultId =
83
+ !resourceFromProp ||
84
+ resourceFromProp ===
85
+ (routerType === "legacy"
86
+ ? legacyResourceFromRoute
87
+ : newResourceNameFromRouter)
88
+ ? params?.id ??
89
+ (routerType === "legacy" ? legacyIdFromParams : idFromRouter)
90
+ : params?.id;
91
+
92
+ /** `resourceName` fallback value depends on the router type */
93
+ const resourceName =
94
+ resourceFromProp ??
95
+ (routerType === "legacy"
96
+ ? legacyResourceFromRoute
97
+ : newResourceNameFromRouter);
98
+
99
+ let resource: IResourceItem | undefined;
100
+
101
+ const resourceWithRoute = useResourceWithRoute();
102
+
103
+ if (routerType === "legacy") {
104
+ if (resourceName) {
105
+ resource = resourceWithRoute(resourceName);
106
+ }
107
+ } else {
108
+ /** If `resource` is provided by the user, then try to pick the resource of create a dummy one */
109
+ if (resourceFromProp) {
110
+ const picked = pickResource(resourceFromProp, resources);
111
+ if (picked) {
112
+ resource = picked;
113
+ } else {
114
+ resource = {
115
+ name: resourceFromProp,
116
+ route: resourceFromProp,
117
+ };
118
+ }
119
+ } else {
120
+ /** If `resource` is not provided, check the resource from the router params */
121
+ if (typeof resourceFromRouter === "string") {
122
+ const picked = pickResource(resourceFromRouter, resources);
123
+ if (picked) {
124
+ resource = picked;
125
+ } else {
126
+ resource = {
127
+ name: resourceFromRouter,
128
+ route: resourceFromRouter,
129
+ };
130
+ }
131
+ } else {
132
+ /** If `resource` is passed as an IResourceItem, use it or `resource` is undefined and cannot be inferred. */
133
+ resource = resourceFromRouter;
134
+ }
135
+ }
136
+ }
137
+
22
138
  const { data } = useCan({
23
- resource,
24
- action,
25
- params,
139
+ resource: resourceFromProp ?? resource?.name,
140
+ action:
141
+ action ??
142
+ (routerType === "legacy"
143
+ ? legacyActionFromParams
144
+ : actionFromRouter) ??
145
+ "",
146
+ params: params ?? {
147
+ id: defaultId,
148
+ resource: resource,
149
+ },
26
150
  });
27
151
 
28
152
  if (data?.can) {
@@ -5,5 +5,5 @@ export * from "./undoableQueue";
5
5
  export { LayoutWrapper } from "./layoutWrapper";
6
6
  export { Authenticated } from "./authenticated";
7
7
  export { RouteChangeHandler } from "./routeChangeHandler";
8
- export { CanAccess } from "./canAccess";
8
+ export { CanAccess, CanAccessProps } from "./canAccess";
9
9
  export { GitHubBanner } from "./gh-banner";