@firecms/core 3.0.0-canary.84 → 3.0.0-canary.85

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.
@@ -8,7 +8,7 @@ import { StorageSource } from "./storage";
8
8
  * to do it as the result of a hook.
9
9
  * @group Hooks and utilities
10
10
  */
11
- export type AuthController<UserType extends User = any, ExtraData extends any = any> = {
11
+ export type AuthController<UserType extends User = any, ExtraData = any> = {
12
12
  /**
13
13
  * The user currently logged in
14
14
  * The values can be: the user object, null if they skipped login
@@ -55,9 +55,8 @@ export interface DeleteEntityProps<M extends Record<string, any> = any> {
55
55
  entity: Entity<M>;
56
56
  }
57
57
  /**
58
- * Implement this interface and pass it to a {@link FireCMS}
59
- * to connect it to your data source.
60
- * A Firestore implementation of this interface can be found in {@link useFirestoreDataSource}
58
+ * Component in charge of communicating with the data source.
59
+ * Usually you won't need to implement this interface, but a {@link DataSourceDelegate} instead.
61
60
  * @group Datasource
62
61
  */
63
62
  export interface DataSource {
@@ -172,6 +171,10 @@ export type ListenCollectionDelegateProps<M extends Record<string, any> = any> =
172
171
  isCollectionGroup?: boolean;
173
172
  };
174
173
  export interface DataSourceDelegate {
174
+ /**
175
+ * Key that identifies this data source delegate
176
+ */
177
+ key: string;
175
178
  /**
176
179
  * Fetch data from a collection
177
180
  * @param path
@@ -220,8 +223,8 @@ export interface DataSourceDelegate {
220
223
  /**
221
224
  * Save entity to the specified path
222
225
  * @param path
223
- * @param id
224
- * @param collection
226
+ * @param entityId
227
+ * @param values
225
228
  * @param status
226
229
  */
227
230
  saveEntity<M extends Record<string, any> = any>({ path, entityId, values, status }: SaveEntityDelegateProps<M>): Promise<Entity<M>>;
@@ -256,7 +259,7 @@ export interface DataSourceDelegate {
256
259
  /**
257
260
  * Get the object to generate the current time in the datasource
258
261
  */
259
- currentTime(): any;
262
+ currentTime?: () => any;
260
263
  delegateToCMSModel: (data: any) => any;
261
264
  cmsToDelegateModel: (data: any) => any;
262
265
  setDateToMidnight: (input?: any) => any;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.84",
4
+ "version": "3.0.0-canary.85",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -46,8 +46,8 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@firecms/formex": "^3.0.0-canary.84",
50
- "@firecms/ui": "^3.0.0-canary.84",
49
+ "@firecms/formex": "^3.0.0-canary.85",
50
+ "@firecms/ui": "^3.0.0-canary.85",
51
51
  "@fontsource/jetbrains-mono": "^5.0.20",
52
52
  "@hello-pangea/dnd": "^16.6.0",
53
53
  "@radix-ui/react-portal": "^1.1.1",
@@ -80,29 +80,29 @@
80
80
  "@testing-library/react": "^15.0.7",
81
81
  "@testing-library/user-event": "^14.5.2",
82
82
  "@types/jest": "^29.5.12",
83
- "@types/node": "^20.14.9",
83
+ "@types/node": "^20.14.12",
84
84
  "@types/object-hash": "^3.0.6",
85
85
  "@types/react": "^18.3.3",
86
86
  "@types/react-dom": "^18.3.0",
87
87
  "@types/react-measure": "^2.0.12",
88
88
  "@vitejs/plugin-react": "^4.3.1",
89
89
  "cross-env": "^7.0.3",
90
- "firebase": "^10.12.2",
90
+ "firebase": "^10.12.4",
91
91
  "jest": "^29.7.0",
92
92
  "npm-run-all": "^4.1.5",
93
- "react-router": "^6.24.0",
94
- "react-router-dom": "^6.24.0",
95
- "ts-jest": "^29.1.5",
93
+ "react-router": "^6.25.1",
94
+ "react-router-dom": "^6.25.1",
95
+ "ts-jest": "^29.2.3",
96
96
  "ts-node": "^10.9.2",
97
97
  "tsd": "^0.31.1",
98
- "typescript": "^5.5.3",
99
- "vite": "^5.3.2"
98
+ "typescript": "^5.5.4",
99
+ "vite": "^5.3.4"
100
100
  },
101
101
  "files": [
102
102
  "dist",
103
103
  "src"
104
104
  ],
105
- "gitHead": "f286f012efde63060e83eeac5da67a866f1026e6",
105
+ "gitHead": "e7ba408552dfc57dbbdb5a49ad7415f1f1381256",
106
106
  "publishConfig": {
107
107
  "access": "public"
108
108
  },
@@ -67,6 +67,7 @@ export const TableReferenceFieldSuccess = React.memo(
67
67
  }, [updateValue]);
68
68
 
69
69
  const onMultipleEntitiesSelected = useCallback((entities: Entity<any>[]) => {
70
+ console.log("onMultipleEntitiesSelected", entities);
70
71
  updateValue(entities.map((e) => getReferenceFrom(e)));
71
72
  }, [updateValue]);
72
73
 
@@ -199,6 +199,7 @@ const EntityPreviewContainerInner = React.forwardRef<HTMLDivElement, EntityPrevi
199
199
  }}
200
200
  className={cls(
201
201
  "bg-white dark:bg-gray-900",
202
+ "min-h-[42px]",
202
203
  fullwidth ? "w-full" : "",
203
204
  "items-center",
204
205
  hover ? "hover:bg-slate-50 dark:hover:bg-gray-800 group-hover:bg-slate-50 dark:group-hover:bg-gray-800" : "",
@@ -95,7 +95,7 @@ export function DateTimeFilterField({
95
95
  size={"medium"}
96
96
  locale={locale}
97
97
  value={internalValue ?? undefined}
98
- onChange={(dateValue: Date | undefined) => {
98
+ onChange={(dateValue: Date | null) => {
99
99
  updateFilter(operation, dateValue === null ? undefined : dateValue);
100
100
  }}
101
101
  clearable={true}
@@ -82,7 +82,7 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
82
82
  onAnalyticsEvent
83
83
  }), []);
84
84
 
85
- const accessResponse = useProjectLog(authController, plugins);
85
+ const accessResponse = useProjectLog(authController, dataSourceDelegate, plugins);
86
86
 
87
87
  if (navigationController.navigationLoadingError) {
88
88
  return (
@@ -43,7 +43,7 @@ export function DateTimeFieldBinding({
43
43
  <>
44
44
  <DateTimeField
45
45
  value={internalValue}
46
- onChange={(dateValue) => setValue(dateValue ?? null)}
46
+ onChange={(dateValue) => setValue(dateValue)}
47
47
  size={"medium"}
48
48
  mode={property.mode}
49
49
  clearable={property.clearable}
@@ -1,4 +1,4 @@
1
- import { useContext, useMemo } from "react";
1
+ import { useContext } from "react";
2
2
  import { DataSource, EntityCollection } from "../../types";
3
3
  import { DataSourceContext } from "../../contexts/DataSourceContext";
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef, useState } from "react";
2
- import { AuthController, FireCMSPlugin } from "../types";
2
+ import { AuthController, DataSourceDelegate, FireCMSPlugin } from "../types";
3
3
 
4
4
  export const DEFAULT_SERVER_DEV = "https://api-kdoe6pj3qq-ey.a.run.app";
5
5
  export const DEFAULT_SERVER = "https://api-drplyi3b6q-ey.a.run.app";
@@ -9,17 +9,26 @@ export type AccessResponse = {
9
9
  message?: string;
10
10
  }
11
11
 
12
- async function makeRequest(authController: AuthController, pluginKeys: string[] | undefined) {
13
- const firebaseToken = await authController.getAuthToken();
12
+ async function makeRequest(authController: AuthController, dataSourceKey: string, pluginKeys: string[] | undefined) {
13
+ let idToken: string | null;
14
+ try {
15
+ idToken = await authController.getAuthToken();
16
+ } catch (e) {
17
+ idToken = null;
18
+ }
14
19
  return fetch(DEFAULT_SERVER + "/access_log",
15
20
  {
16
21
  // mode: "no-cors",
17
22
  method: "POST",
18
23
  headers: {
19
24
  "Content-Type": "application/json",
20
- Authorization: `Basic ${firebaseToken}`,
25
+ Authorization: `Basic ${idToken}`
21
26
  },
22
- body: JSON.stringify({ plugins: pluginKeys })
27
+ body: JSON.stringify({
28
+ email: authController.user?.email ?? null,
29
+ datasource: dataSourceKey,
30
+ plugins: pluginKeys
31
+ })
23
32
  })
24
33
  .then(async (res) => {
25
34
  return res.json();
@@ -27,15 +36,17 @@ async function makeRequest(authController: AuthController, pluginKeys: string[]
27
36
  }
28
37
 
29
38
  export function useProjectLog(authController: AuthController,
39
+ dataSourceDelegate: DataSourceDelegate,
30
40
  plugins?: FireCMSPlugin<any, any, any>[]): AccessResponse | null {
31
41
  const [accessResponse, setAccessResponse] = useState<AccessResponse | null>(null);
32
42
  const accessedUserRef = useRef<string | null>(null);
43
+ const dataSourceKey = dataSourceDelegate.key;
33
44
  const pluginKeys = plugins?.map(plugin => plugin.key);
34
45
  useEffect(() => {
35
46
  if (authController.user && authController.user.uid !== accessedUserRef.current && !authController.initialLoading) {
36
- makeRequest(authController, pluginKeys).then(setAccessResponse);
47
+ makeRequest(authController, dataSourceKey, pluginKeys).then(setAccessResponse);
37
48
  accessedUserRef.current = authController.user.uid;
38
49
  }
39
- }, [authController, pluginKeys]);
50
+ }, [authController, dataSourceKey, pluginKeys]);
40
51
  return accessResponse;
41
52
  }
@@ -216,7 +216,7 @@ export function useBuildDataSource({
216
216
  inputValues: firestoreValues,
217
217
  properties,
218
218
  status,
219
- timestampNowValue: delegate.currentTime(),
219
+ timestampNowValue: delegate.currentTime?.() ?? new Date(),
220
220
  setDateToMidnight: delegate.setDateToMidnight
221
221
  })
222
222
  : firestoreValues;
@@ -290,7 +290,7 @@ export function useBuildDataSource({
290
290
  filter,
291
291
  orderBy,
292
292
  order,
293
- isCollectionGroup: Boolean(collection.collectionGroup) ?? false
293
+ isCollectionGroup: Boolean(collection.collectionGroup)
294
294
  });
295
295
  } : undefined,
296
296
 
@@ -9,7 +9,7 @@ import { StorageSource } from "./storage";
9
9
  * to do it as the result of a hook.
10
10
  * @group Hooks and utilities
11
11
  */
12
- export type AuthController<UserType extends User = any, ExtraData extends any = any> = {
12
+ export type AuthController<UserType extends User = any, ExtraData = any> = {
13
13
 
14
14
  /**
15
15
  * The user currently logged in
@@ -82,7 +82,7 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
82
82
  * as the title in entity related views and references.
83
83
  * If not specified, the first property simple text property will be used.
84
84
  */
85
- titleProperty?: keyof M,
85
+ titleProperty?: keyof M;
86
86
 
87
87
  /**
88
88
  * Can this collection be edited by the end user.
@@ -1,4 +1,4 @@
1
- import { Entity, EntityReference, EntityStatus, EntityValues, GeoPoint } from "./entities";
1
+ import { Entity, EntityStatus, EntityValues } from "./entities";
2
2
  import { EntityCollection, FilterValues } from "./collections";
3
3
  import { ResolvedEntityCollection } from "./resolved_entities";
4
4
  import { FireCMSContext } from "./firecms_context";
@@ -66,9 +66,8 @@ export interface DeleteEntityProps<M extends Record<string, any> = any> {
66
66
  }
67
67
 
68
68
  /**
69
- * Implement this interface and pass it to a {@link FireCMS}
70
- * to connect it to your data source.
71
- * A Firestore implementation of this interface can be found in {@link useFirestoreDataSource}
69
+ * Component in charge of communicating with the data source.
70
+ * Usually you won't need to implement this interface, but a {@link DataSourceDelegate} instead.
72
71
  * @group Datasource
73
72
  */
74
73
  export interface DataSource {
@@ -254,6 +253,12 @@ export type ListenCollectionDelegateProps<M extends Record<string, any> = any> =
254
253
  };
255
254
 
256
255
  export interface DataSourceDelegate {
256
+
257
+ /**
258
+ * Key that identifies this data source delegate
259
+ */
260
+ key: string;
261
+
257
262
  /**
258
263
  * Fetch data from a collection
259
264
  * @param path
@@ -332,8 +337,8 @@ export interface DataSourceDelegate {
332
337
  /**
333
338
  * Save entity to the specified path
334
339
  * @param path
335
- * @param id
336
- * @param collection
340
+ * @param entityId
341
+ * @param values
337
342
  * @param status
338
343
  */
339
344
  saveEntity<M extends Record<string, any> = any>({
@@ -379,7 +384,7 @@ export interface DataSourceDelegate {
379
384
  /**
380
385
  * Get the object to generate the current time in the datasource
381
386
  */
382
- currentTime(): any;
387
+ currentTime?: () => any;
383
388
 
384
389
  delegateToCMSModel: (data: any) => any;
385
390