@firecms/core 3.0.0-beta.4.pre.1 → 3.0.0-beta.5

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 (70) hide show
  1. package/README.md +1 -1
  2. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  3. package/dist/components/EntityPreview.d.ts +2 -2
  4. package/dist/components/FieldCaption.d.ts +1 -0
  5. package/dist/contexts/AuthControllerContext.d.ts +1 -1
  6. package/dist/hooks/data/delete.d.ts +2 -2
  7. package/dist/hooks/data/save.d.ts +1 -1
  8. package/dist/hooks/data/useDataSource.d.ts +1 -1
  9. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  10. package/dist/hooks/index.d.ts +1 -0
  11. package/dist/hooks/useBuildNavigationController.d.ts +1 -2
  12. package/dist/hooks/useProjectLog.d.ts +2 -2
  13. package/dist/hooks/useValidateAuthenticator.d.ts +25 -0
  14. package/dist/index.es.js +2333 -2257
  15. package/dist/index.es.js.map +1 -1
  16. package/dist/index.umd.js +5 -5
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/internal/useRestoreScroll.d.ts +1 -1
  19. package/dist/preview/PropertyPreviewProps.d.ts +1 -4
  20. package/dist/types/auth.d.ts +30 -1
  21. package/dist/types/collections.d.ts +3 -3
  22. package/dist/types/datasource.d.ts +1 -1
  23. package/dist/types/entity_callbacks.d.ts +2 -2
  24. package/dist/types/index.d.ts +1 -0
  25. package/dist/types/navigation.d.ts +4 -4
  26. package/dist/types/plugins.d.ts +2 -2
  27. package/dist/types/roles.d.ts +31 -0
  28. package/dist/types/storage.d.ts +11 -3
  29. package/dist/types/user.d.ts +5 -0
  30. package/dist/util/collections.d.ts +1 -1
  31. package/dist/util/useTraceUpdate.d.ts +1 -0
  32. package/package.json +10 -10
  33. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -1
  34. package/src/components/EntityPreview.tsx +5 -2
  35. package/src/components/FieldCaption.tsx +1 -0
  36. package/src/components/HomePage/DefaultHomePage.tsx +1 -1
  37. package/src/components/HomePage/NavigationCard.tsx +1 -1
  38. package/src/components/ReferenceWidget.tsx +1 -1
  39. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +1 -1
  40. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  41. package/src/contexts/AuthControllerContext.tsx +1 -1
  42. package/src/core/FireCMS.tsx +1 -1
  43. package/src/form/EntityForm.tsx +1 -1
  44. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  45. package/src/hooks/data/delete.ts +3 -3
  46. package/src/hooks/data/save.ts +1 -1
  47. package/src/hooks/data/useDataSource.tsx +1 -1
  48. package/src/hooks/data/useEntityFetch.tsx +3 -3
  49. package/src/hooks/index.tsx +2 -0
  50. package/src/hooks/useBuildNavigationController.tsx +63 -43
  51. package/src/hooks/useProjectLog.tsx +7 -5
  52. package/src/hooks/useValidateAuthenticator.tsx +135 -0
  53. package/src/internal/useBuildSideEntityController.tsx +3 -0
  54. package/src/preview/PropertyPreviewProps.tsx +1 -11
  55. package/src/preview/components/BooleanPreview.tsx +4 -2
  56. package/src/preview/components/ReferencePreview.tsx +1 -1
  57. package/src/types/auth.tsx +40 -1
  58. package/src/types/collections.ts +3 -3
  59. package/src/types/datasource.ts +1 -1
  60. package/src/types/entity_callbacks.ts +2 -2
  61. package/src/types/index.ts +1 -0
  62. package/src/types/navigation.ts +6 -6
  63. package/src/types/plugins.tsx +2 -2
  64. package/src/types/properties.ts +2 -1
  65. package/src/types/roles.ts +41 -0
  66. package/src/types/storage.ts +12 -3
  67. package/src/types/user.ts +7 -0
  68. package/src/util/collections.ts +1 -1
  69. package/src/util/strings.ts +2 -2
  70. package/src/util/useTraceUpdate.tsx +2 -1
@@ -2,5 +2,5 @@ import React from "react";
2
2
  export declare function useRestoreScroll(): {
3
3
  containerRef: React.RefObject<HTMLDivElement>;
4
4
  scroll: number;
5
- direction: "down" | "up";
5
+ direction: "up" | "down";
6
6
  };
@@ -6,7 +6,7 @@ export type PreviewSize = "medium" | "small" | "tiny";
6
6
  /**
7
7
  * @group Preview components
8
8
  */
9
- export interface PropertyPreviewProps<T extends CMSType = any, CustomProps = any, M extends Record<string, any> = Record<string, any>> {
9
+ export interface PropertyPreviewProps<T extends CMSType = any, CustomProps = any> {
10
10
  /**
11
11
  * Name of the property
12
12
  */
@@ -19,9 +19,6 @@ export interface PropertyPreviewProps<T extends CMSType = any, CustomProps = any
19
19
  * Property this display is related to
20
20
  */
21
21
  property: Property<T> | ResolvedProperty<T>;
22
- /**
23
- * Click handler
24
- */
25
22
  /**
26
23
  * Desired size of the preview, depending on the context.
27
24
  */
@@ -1,16 +1,23 @@
1
1
  import { User } from "./user";
2
+ import { Role } from "./roles";
3
+ import { DataSourceDelegate } from "./datasource";
4
+ import { StorageSource } from "./storage";
2
5
  /**
3
6
  * Controller for retrieving the logged user or performing auth related operations.
4
7
  * Note that if you are implementing your AuthController, you probably will want
5
8
  * to do it as the result of a hook.
6
9
  * @group Hooks and utilities
7
10
  */
8
- export type AuthController<UserType extends User = User, ExtraData extends any = any> = {
11
+ export type AuthController<UserType extends User = any, ExtraData extends any = any> = {
9
12
  /**
10
13
  * The user currently logged in
11
14
  * The values can be: the user object, null if they skipped login
12
15
  */
13
16
  user: UserType | null;
17
+ /**
18
+ * Roles related to the logged user
19
+ */
20
+ roles?: Role[];
14
21
  /**
15
22
  * Initial loading flag. It is used not to display the login screen
16
23
  * when the app first loads, and it has not been checked whether the user
@@ -45,3 +52,25 @@ export type AuthController<UserType extends User = User, ExtraData extends any =
45
52
  extra: ExtraData;
46
53
  setExtra: (extra: ExtraData) => void;
47
54
  };
55
+ /**
56
+ * Implement this function to allow access to specific users.
57
+ * @group Hooks and utilities
58
+ */
59
+ export type Authenticator<UserType extends User = User, Controller extends AuthController<UserType> = AuthController<UserType>> = (props: {
60
+ /**
61
+ * Logged-in user or null
62
+ */
63
+ user: UserType | null;
64
+ /**
65
+ * AuthController
66
+ */
67
+ authController: Controller;
68
+ /**
69
+ * Connector to your database, e.g. your Firestore database
70
+ */
71
+ dataSourceDelegate: DataSourceDelegate;
72
+ /**
73
+ * Used storage implementation
74
+ */
75
+ storageSource: StorageSource;
76
+ }) => boolean | Promise<boolean>;
@@ -16,7 +16,7 @@ import { EntityOverrides } from "./entity_overrides";
16
16
  *
17
17
  * @group Models
18
18
  */
19
- export interface EntityCollection<M extends Record<string, any> = any, UserType extends User = User> {
19
+ export interface EntityCollection<M extends Record<string, any> = any, UserType extends User = any> {
20
20
  /**
21
21
  * You can set an alias that will be used internally instead of the `path`.
22
22
  * The `alias` value will be used to determine the URL of the collection,
@@ -128,7 +128,7 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
128
128
  * is being created, updated or deleted.
129
129
  * Useful for adding your own logic or blocking the execution of the operation.
130
130
  */
131
- callbacks?: EntityCallbacks<M>;
131
+ callbacks?: EntityCallbacks<M, UserType>;
132
132
  /**
133
133
  * Builder for rendering additional components such as buttons in the
134
134
  * collection toolbar
@@ -382,7 +382,7 @@ export interface AdditionalFieldDelegate<M extends Record<string, any> = any, Us
382
382
  */
383
383
  value?: (props: {
384
384
  entity: Entity<M>;
385
- context: FireCMSContext;
385
+ context: FireCMSContext<any>;
386
386
  }) => string | number | Promise<string | number> | undefined;
387
387
  }
388
388
  /**
@@ -7,7 +7,7 @@ import { ResolvedEntityCollection } from "./resolved_entities";
7
7
  export interface FetchEntityProps<M extends Record<string, any> = any> {
8
8
  path: string;
9
9
  entityId: string;
10
- collection?: EntityCollection<M>;
10
+ collection?: EntityCollection<M, any>;
11
11
  }
12
12
  /**
13
13
  * @group Datasource
@@ -63,7 +63,7 @@ export interface EntityOnFetchProps<M extends Record<string, any> = any, UserTyp
63
63
  /**
64
64
  * Collection of the entity
65
65
  */
66
- collection: EntityCollection<M>;
66
+ collection: EntityCollection<M, UserType>;
67
67
  /**
68
68
  * Full path of the CMS where this collection is being fetched.
69
69
  * Might contain unresolved aliases.
@@ -155,7 +155,7 @@ export interface EntityOnDeleteProps<M extends Record<string, any> = any, UserTy
155
155
  /**
156
156
  * Context of the app status
157
157
  */
158
- context: FireCMSContext;
158
+ context: FireCMSContext<UserType>;
159
159
  }
160
160
  /**
161
161
  * Parameters passed to hooks when an entity is deleted
@@ -22,6 +22,7 @@ export * from "./local_config_persistence";
22
22
  export * from "./plugins";
23
23
  export * from "./analytics";
24
24
  export * from "./firecms";
25
+ export * from "./roles";
25
26
  export * from "./appcheck";
26
27
  export * from "./export_import";
27
28
  export * from "./modify_collections";
@@ -6,7 +6,7 @@ import { EntityReference } from "./entities";
6
6
  * attributes.
7
7
  * @group Models
8
8
  */
9
- export type NavigationController = {
9
+ export type NavigationController<EC extends EntityCollection = EntityCollection<any>> = {
10
10
  /**
11
11
  * List of the mapped collections in the CMS.
12
12
  * Each entry relates to a collection in the root database.
@@ -47,15 +47,15 @@ export type NavigationController = {
47
47
  * Get the collection configuration for a given path.
48
48
  * The collection is resolved from the given path or alias.
49
49
  */
50
- getCollection: <EC extends EntityCollection = EntityCollection<any>>(pathOrAlias: string, entityId?: string, includeUserOverride?: boolean) => EC | undefined;
50
+ getCollection: (pathOrAlias: string, entityId?: string, includeUserOverride?: boolean) => EC | undefined;
51
51
  /**
52
52
  * Get the collection configuration from its parent path segments.
53
53
  */
54
- getCollectionFromIds: <EC extends EntityCollection = EntityCollection<any>>(ids: string[]) => EC | undefined;
54
+ getCollectionFromIds: (ids: string[]) => EC | undefined;
55
55
  /**
56
56
  * Get the collection configuration from its parent path segments.
57
57
  */
58
- getCollectionFromPaths: <EC extends EntityCollection = EntityCollection<any>>(pathSegments: string[]) => EC | undefined;
58
+ getCollectionFromPaths: (pathSegments: string[]) => EC | undefined;
59
59
  /**
60
60
  * Default path under the navigation routes of the CMS will be created
61
61
  */
@@ -13,9 +13,9 @@ import { ResolvedProperty } from "./resolved_entities";
13
13
  */
14
14
  export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollection = EntityCollection, COL_ACTIONS_PROPS = any> = {
15
15
  /**
16
- * Name of the plugin
16
+ * Key of the plugin. This is used to identify the plugin in the CMS.
17
17
  */
18
- name: string;
18
+ key: string;
19
19
  /**
20
20
  * If this flag is set to true, no content will be shown in the CMS
21
21
  * until the plugin is fully loaded.
@@ -0,0 +1,31 @@
1
+ import { Permissions } from "../index";
2
+ export type Role = {
3
+ /**
4
+ * ID of the role
5
+ */
6
+ id: string;
7
+ /**
8
+ * Name of the role
9
+ */
10
+ name: string;
11
+ /**
12
+ * If this flag is true, the user can perform any action
13
+ */
14
+ isAdmin?: boolean;
15
+ /**
16
+ * Default permissions for all collections for this role.
17
+ * You can override this values at the collection level using
18
+ * {@link collectionPermissions}
19
+ */
20
+ defaultPermissions?: Permissions;
21
+ /**
22
+ * Record of stripped collection ids to their permissions.
23
+ * @see stripCollectionPath
24
+ */
25
+ collectionPermissions?: Record<string, Permissions>;
26
+ config?: {
27
+ createCollections?: boolean;
28
+ editCollections?: boolean | "own";
29
+ deleteCollections?: boolean | "own";
30
+ };
31
+ };
@@ -6,6 +6,7 @@ export interface UploadFileProps {
6
6
  fileName?: string;
7
7
  path?: string;
8
8
  metadata?: any;
9
+ bucket?: string;
9
10
  }
10
11
  /**
11
12
  * @group Models
@@ -15,6 +16,10 @@ export interface UploadFileResult {
15
16
  * Storage path including the file name where the file was uploaded.
16
17
  */
17
18
  path: string;
19
+ /**
20
+ * Bucket where the file was uploaded
21
+ */
22
+ bucket: string;
18
23
  }
19
24
  /**
20
25
  * @group Models
@@ -66,17 +71,20 @@ export interface StorageSource {
66
71
  * @param fileName
67
72
  * @param path
68
73
  * @param metadata
74
+ * @param bucket
69
75
  */
70
- uploadFile: ({ file, fileName, path, metadata }: UploadFileProps) => Promise<UploadFileResult>;
76
+ uploadFile: ({ file, fileName, path, metadata, bucket }: UploadFileProps) => Promise<UploadFileResult>;
71
77
  /**
72
78
  * Convert a storage path or URL into a download configuration
73
79
  * @param path
80
+ * @param bucket
74
81
  */
75
- getDownloadURL: (pathOrUrl: string) => Promise<DownloadConfig>;
82
+ getDownloadURL: (pathOrUrl: string, bucket?: string) => Promise<DownloadConfig>;
76
83
  /**
77
84
  * Get a file from a storage path.
78
85
  * It returns null if the file does not exist.
79
86
  * @param props
87
+ * @param bucket
80
88
  */
81
- getFile: (path: string) => Promise<File | null>;
89
+ getFile: (path: string, bucket?: string) => Promise<File | null>;
82
90
  }
@@ -1,3 +1,4 @@
1
+ import { Role } from "./roles";
1
2
  /**
2
3
  * This interface represents a user.
3
4
  * It has some of the same fields as a Firebase User.
@@ -33,4 +34,8 @@ export type User = {
33
34
  *
34
35
  */
35
36
  readonly isAnonymous: boolean;
37
+ /**
38
+ *
39
+ */
40
+ roles?: Role[];
36
41
  };
@@ -8,4 +8,4 @@ export declare function resolveDefaultSelectedView(defaultSelectedView: string |
8
8
  * @param collections
9
9
  * @param permissionsBuilder
10
10
  */
11
- export declare const applyPermissionsFunctionIfEmpty: (collections: EntityCollection[], permissionsBuilder?: PermissionsBuilder) => EntityCollection[];
11
+ export declare const applyPermissionsFunctionIfEmpty: (collections: EntityCollection[], permissionsBuilder?: PermissionsBuilder<any, any>) => EntityCollection[];
@@ -1 +1,2 @@
1
+ export declare function printChanged(props: any, prev: any, path?: string | undefined, depth?: number | undefined, maxDepth?: number | undefined): void;
1
2
  export declare function useTraceUpdate(props: any, maxDepth?: number): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-beta.4.pre.1",
4
+ "version": "3.0.0-beta.5",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -41,13 +41,13 @@
41
41
  ".": {
42
42
  "import": "./dist/index.es.js",
43
43
  "require": "./dist/index.umd.js",
44
- "types": "./dist/src/index.d.ts"
44
+ "types": "./dist/index.d.ts"
45
45
  },
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@firecms/formex": "^3.0.0-beta.4.pre.1",
50
- "@firecms/ui": "^3.0.0-beta.4.pre.1",
49
+ "@firecms/formex": "^3.0.0-beta.5",
50
+ "@firecms/ui": "^3.0.0-beta.5",
51
51
  "@fontsource/ibm-plex-mono": "^5.0.12",
52
52
  "@fontsource/roboto": "^5.0.12",
53
53
  "@hello-pangea/dnd": "^16.5.0",
@@ -69,8 +69,8 @@
69
69
  "firebase": "^10.5.2",
70
70
  "react": "^18.2.0",
71
71
  "react-dom": "^18.2.0",
72
- "react-router": "^6.2.0",
73
- "react-router-dom": "^6.2.0"
72
+ "react-router": "^6.22.0",
73
+ "react-router-dom": "^6.22.0"
74
74
  },
75
75
  "eslintConfig": {
76
76
  "extends": [
@@ -103,19 +103,19 @@
103
103
  "firebase": "^10.9.0",
104
104
  "jest": "^29.7.0",
105
105
  "npm-run-all": "^4.1.5",
106
- "react-router": "^6.22.3",
107
- "react-router-dom": "^6.22.3",
106
+ "react-router": "^6.22.0",
107
+ "react-router-dom": "^6.22.0",
108
108
  "ts-jest": "^29.1.2",
109
109
  "ts-node": "^10.9.2",
110
110
  "tsd": "^0.30.7",
111
111
  "typescript": "^5.4.2",
112
- "vite": "^5.1.6"
112
+ "vite": "^5.2.3"
113
113
  },
114
114
  "files": [
115
115
  "dist",
116
116
  "src"
117
117
  ],
118
- "gitHead": "a197c6698a64aeb8f9608e6a177a7ecd149920de",
118
+ "gitHead": "8bf864185c9617aa3f120e59c873c8b8bda8dac4",
119
119
  "publishConfig": {
120
120
  "access": "public"
121
121
  }
@@ -29,7 +29,7 @@ export function TableReferenceField(props: TableReferenceFieldProps) {
29
29
 
30
30
  const navigationController = useNavigationController();
31
31
  const { path } = props;
32
- const collection = navigationController.getCollection<EntityCollection>(path);
32
+ const collection = navigationController.getCollection(path);
33
33
  if (!collection) {
34
34
  if (customizationController.components?.missingReference) {
35
35
  return <customizationController.components.missingReference path={path}/>;
@@ -49,7 +49,7 @@ export function EntityPreview({
49
49
 
50
50
  const navigationController = useNavigationController();
51
51
 
52
- const collection = collectionProp ?? navigationController.getCollection<EntityCollection>(entity.path);
52
+ const collection = collectionProp ?? navigationController.getCollection(entity.path);
53
53
 
54
54
  if (!collection) {
55
55
  throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);
@@ -168,9 +168,10 @@ export function EntityPreview({
168
168
  </EntityPreviewContainer>;
169
169
  }
170
170
 
171
- type EntityPreviewContainerProps = {
171
+ export type EntityPreviewContainerProps = {
172
172
  children: React.ReactNode;
173
173
  hover?: boolean;
174
+ fullwidth?: boolean;
174
175
  size: PreviewSize;
175
176
  className?: string;
176
177
  style?: React.CSSProperties;
@@ -184,6 +185,7 @@ const EntityPreviewContainerInner = React.forwardRef<HTMLDivElement, EntityPrevi
184
185
  size,
185
186
  style,
186
187
  className,
188
+ fullwidth = true,
187
189
  ...props
188
190
  }, ref) => {
189
191
  return <div
@@ -195,6 +197,7 @@ const EntityPreviewContainerInner = React.forwardRef<HTMLDivElement, EntityPrevi
195
197
  }}
196
198
  className={cn(
197
199
  "bg-white dark:bg-gray-900",
200
+ fullwidth ? "w-full" : "",
198
201
  "items-center",
199
202
  hover ? "hover:bg-slate-50 dark:hover:bg-gray-800 group-hover:bg-slate-50 dark:group-hover:bg-gray-800" : "",
200
203
  size === "tiny" ? "p-1" : "p-2",
@@ -1,3 +1,4 @@
1
+ import React from "react";
1
2
  import { Typography } from "@firecms/ui";
2
3
 
3
4
  export function FieldCaption({
@@ -102,7 +102,7 @@ export function DefaultHomePage({
102
102
  return (
103
103
  <NavigationGroup
104
104
  group={section.title}
105
- key={`plugin_section_${plugin.name}`}>
105
+ key={`plugin_section_${plugin.key}`}>
106
106
  {section.children}
107
107
  </NavigationGroup>
108
108
  );
@@ -52,7 +52,7 @@ export function NavigationCard({
52
52
  {description && <Typography variant="body2"
53
53
  color="secondary"
54
54
  component="div">
55
- <Markdown source={description}/>
55
+ <Markdown source={description} size={"small"}/>
56
56
  </Typography>}
57
57
  </div>
58
58
 
@@ -50,7 +50,7 @@ export function ReferenceWidget<M extends Record<string, any>>({
50
50
 
51
51
  const collection: EntityCollection | undefined = useMemo(() => {
52
52
  return navigationController.getCollection(path);
53
- }, [path, navigationController]);
53
+ }, [path, navigationController.getCollection]);
54
54
 
55
55
  // if (!collection) {
56
56
  // throw Error(`Couldn't find the corresponding collection for the path: ${path}`);
@@ -95,7 +95,7 @@ export function DateTimeFilterField({
95
95
  size={"medium"}
96
96
  locale={locale}
97
97
  value={internalValue}
98
- onChange={(dateValue: Date | null) => {
98
+ onChange={(dateValue: Date | undefined) => {
99
99
  updateFilter(operation, dateValue === null ? undefined : dateValue);
100
100
  }}
101
101
  clearable={true}
@@ -25,7 +25,7 @@ export function VirtualTableDateField(props: {
25
25
  return (
26
26
  <DateTimeField
27
27
  value={internalValue ?? undefined}
28
- onChange={(dateValue) => updateValue(dateValue)}
28
+ onChange={(dateValue) => updateValue(dateValue ?? null)}
29
29
  size={"medium"}
30
30
  invisible={true}
31
31
  className={"w-full h-full"}
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
2
  import { AuthController } from "../types";
3
3
 
4
- export const AuthControllerContext = React.createContext<AuthController>({} as AuthController);
4
+ export const AuthControllerContext = React.createContext<AuthController<any, any>>({} as AuthController<any, any>);
@@ -85,7 +85,7 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
85
85
  onAnalyticsEvent
86
86
  }), []);
87
87
 
88
- const accessResponse = useProjectLog(authController);
88
+ const accessResponse = useProjectLog(authController, plugins);
89
89
 
90
90
  if (navigationController.navigationLoadingError) {
91
91
  return (
@@ -443,7 +443,7 @@ function EntityFormInternal<M extends Record<string, any>>({
443
443
  pluginActions.push(...plugins.map((plugin, i) => (
444
444
  plugin.form?.Actions
445
445
  ? <plugin.form.Actions
446
- key={`actions_${plugin.name}`} {...actionProps}/>
446
+ key={`actions_${plugin.key}`} {...actionProps}/>
447
447
  : null
448
448
  )).filter(Boolean));
449
449
  }
@@ -43,7 +43,7 @@ export function DateTimeFieldBinding({
43
43
  <>
44
44
  <DateTimeField
45
45
  value={internalValue}
46
- onChange={(dateValue) => setValue(dateValue)}
46
+ onChange={(dateValue) => setValue(dateValue ?? null)}
47
47
  size={"medium"}
48
48
  mode={property.mode}
49
49
  clearable={property.clearable}
@@ -12,10 +12,10 @@ import {
12
12
  /**
13
13
  * @group Hooks and utilities
14
14
  */
15
- export type DeleteEntityWithCallbacksProps<M extends Record<string, any>> =
15
+ export type DeleteEntityWithCallbacksProps<M extends Record<string, any>, UserType extends User = User> =
16
16
  DeleteEntityProps<M>
17
17
  & {
18
- callbacks?: EntityCallbacks<M>;
18
+ callbacks?: EntityCallbacks<M, UserType>;
19
19
  onDeleteSuccess?: (entity: Entity<M>) => void;
20
20
  onDeleteFailure?: (entity: Entity<M>, e: Error) => void;
21
21
  onPreDeleteHookError?: (entity: Entity<M>, e: Error) => void;
@@ -62,7 +62,7 @@ export async function deleteEntityWithCallbacks<M extends Record<string, any>, U
62
62
 
63
63
  console.debug("Deleting entity", entity.path, entity.id);
64
64
 
65
- const entityDeleteProps: EntityOnDeleteProps<M, UserType> = {
65
+ const entityDeleteProps: EntityOnDeleteProps<M, any> = {
66
66
  entity,
67
67
  collection,
68
68
  entityId: entity.id,
@@ -64,7 +64,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
64
64
  onPreSaveHookError,
65
65
  onSaveSuccessHookError
66
66
  }: SaveEntityWithCallbacksProps<M> & {
67
- collection: EntityCollection<M>,
67
+ collection: EntityCollection<M, UserType>,
68
68
  dataSource: DataSource,
69
69
  context: FireCMSContext<UserType>,
70
70
  }
@@ -6,7 +6,7 @@ import { DataSourceContext } from "../../contexts/DataSourceContext";
6
6
  * Use this hook to get the datasource being used
7
7
  * @group Hooks and utilities
8
8
  */
9
- export const useDataSource = (collection?: EntityCollection): DataSource => {
9
+ export const useDataSource = (collection?: EntityCollection<any, any>): DataSource => {
10
10
  const defaultDataSource = useContext(DataSourceContext);
11
11
  if (collection?.overrides?.dataSource)
12
12
  return collection?.overrides.dataSource;
@@ -7,10 +7,10 @@ import { useFireCMSContext } from "../useFireCMSContext";
7
7
  /**
8
8
  * @group Hooks and utilities
9
9
  */
10
- export interface EntityFetchProps<M extends Record<string, any>> {
10
+ export interface EntityFetchProps<M extends Record<string, any>, UserType extends User = User> {
11
11
  path: string;
12
12
  entityId?: string;
13
- collection: EntityCollection<M>;
13
+ collection: EntityCollection<M, UserType>;
14
14
  useCache?: boolean;
15
15
  }
16
16
 
@@ -41,7 +41,7 @@ export function useEntityFetch<M extends Record<string, any>, UserType extends U
41
41
  entityId,
42
42
  collection,
43
43
  useCache = false
44
- }: EntityFetchProps<M>): EntityFetchResult<M> {
44
+ }: EntityFetchProps<M, UserType>): EntityFetchResult<M> {
45
45
 
46
46
  const dataSource = useDataSource(collection);
47
47
  const navigationController = useNavigationController();
@@ -25,3 +25,5 @@ export * from "./useBuildNavigationController";
25
25
 
26
26
  export * from "./useBuildLocalConfigurationPersistence";
27
27
  export * from "./useBuildModeController";
28
+
29
+ export * from "./useValidateAuthenticator";