@rebasepro/client-firebase 0.3.0 → 0.5.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.
@@ -1,5 +1,5 @@
1
1
  import { ApplicationVerifier, ConfirmationResult, User as FirebaseUser } from "@firebase/auth";
2
- import { AuthController, Role, User } from "@rebasepro/types";
2
+ import type { AuthController, User } from "@rebasepro/types";
3
3
  /**
4
4
  * @group Firebase
5
5
  */
@@ -37,5 +37,5 @@ export type FirebaseAuthController<USER extends User = FirebaseUserWrapper, Extr
37
37
  */
38
38
  skipLogin: () => void;
39
39
  setUser: (user: USER | null) => void;
40
- setUserRoles: (roles: Role[]) => void;
40
+ setUserRoles: (roles: string[]) => void;
41
41
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/client-firebase",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.5.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -14,12 +14,12 @@
14
14
  "fast-equals": "6.0.0",
15
15
  "fuse.js": "^7.3.0",
16
16
  "react-router-dom": "^7.15.1",
17
- "@rebasepro/admin": "0.3.0",
18
- "@rebasepro/common": "0.3.0",
19
- "@rebasepro/types": "0.3.0",
20
- "@rebasepro/core": "0.3.0",
21
- "@rebasepro/ui": "0.3.0",
22
- "@rebasepro/utils": "0.3.0"
17
+ "@rebasepro/common": "0.5.0",
18
+ "@rebasepro/admin": "0.5.0",
19
+ "@rebasepro/ui": "0.5.0",
20
+ "@rebasepro/utils": "0.5.0",
21
+ "@rebasepro/core": "0.5.0",
22
+ "@rebasepro/types": "0.5.0"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "firebase": "^10.12.2 || ^11.0.0 || ^12.0.0",
@@ -6,12 +6,17 @@ import {
6
6
  AuthController,
7
7
  DataDriver,
8
8
  Entity,
9
- Role,
10
9
  User,
11
10
  UserManagementDelegate
12
11
  } from "@rebasepro/types";
13
12
  import { FirebaseAccessGate } from "./useFirebaseAccessGate";
14
13
 
14
+ export interface Role {
15
+ id: string;
16
+ name: string;
17
+ isAdmin?: boolean;
18
+ }
19
+
15
20
  type UserWithRoleIds<USER extends User = User> = Omit<USER, "roles"> & { roles: string[] };
16
21
 
17
22
  export interface UserManagementDelegateParams<CONTROLLER extends AuthController<User> = AuthController<User>> {
@@ -254,12 +259,12 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<User> =
254
259
 
255
260
 
256
261
 
257
- const defineRolesFor: ((user: User) => Role[] | undefined) = useCallback((user) => {
262
+ const defineRolesFor: ((user: User) => string[] | undefined) = useCallback((user) => {
258
263
  if (!usersWithRoleIds) throw Error("Users not loaded");
259
264
  const mgmtUser = usersWithRoleIds.find(u => u.email?.toLowerCase() === user?.email?.toLowerCase());
260
265
  if (!mgmtUser || !mgmtUser.roles) return undefined;
261
- return roles.filter(r => mgmtUser.roles.includes(r.id));
262
- }, [roles, usersWithRoleIds]);
266
+ return mgmtUser.roles;
267
+ }, [usersWithRoleIds]);
263
268
 
264
269
  const accessGate: FirebaseAccessGate<USER> = useCallback(({ user }) => {
265
270
 
@@ -303,9 +308,9 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<User> =
303
308
  }, [loading, users]);
304
309
 
305
310
  const userRoles = authController.user ? defineRolesFor(authController.user) : undefined;
306
- const isAdmin = (userRoles ?? []).some(r => r.id === "admin");
311
+ const isAdmin = (userRoles ?? []).some(r => r === "admin");
307
312
 
308
- const userRoleIds = userRoles?.map(r => r.id);
313
+ const userRoleIds = userRoles;
309
314
  useEffect(() => {
310
315
  console.debug("Setting user roles", {
311
316
  userRoles,
@@ -24,14 +24,14 @@ import {
24
24
  } from "@firebase/auth";
25
25
  import { FirebaseApp } from "@firebase/app";
26
26
  import { FirebaseAuthController, FirebaseSignInOption, FirebaseSignInProvider, FirebaseUserWrapper } from "../types";
27
- import { Role, User } from "@rebasepro/types";
27
+ import type { User } from "@rebasepro/types";
28
28
 
29
29
  export interface FirebaseAuthControllerProps {
30
30
  loading?: boolean;
31
31
  firebaseApp?: FirebaseApp;
32
32
  signInOptions?: Array<FirebaseSignInProvider | FirebaseSignInOption>;
33
33
  onSignOut?: () => void;
34
- defineRolesFor?: (user: User) => Promise<Role[] | undefined> | Role[] | undefined;
34
+ defineRolesFor?: (user: User) => Promise<string[] | undefined> | string[] | undefined;
35
35
  }
36
36
 
37
37
  /**
@@ -53,13 +53,11 @@ export const useFirebaseAuthController = <USER extends FirebaseUserWrapper = any
53
53
  const [authLoading, setAuthLoading] = useState(true);
54
54
  const [loginSkipped, setLoginSkipped] = useState<boolean>(false);
55
55
  const [confirmationResult, setConfirmationResult] = useState<undefined | ConfirmationResult>();
56
- const [userRoles, _setUserRoles] = useState<Role[] | undefined>();
56
+ const [userRoles, _setUserRoles] = useState<string[] | undefined>();
57
57
  const [extra, setExtra] = useState<any>();
58
58
 
59
- const setUserRoles = useCallback((roles: Role[] | undefined) => {
60
- const currentRoleIds = userRoles?.map(r => r.id);
61
- const newRoleIds = roles?.map(r => r.id);
62
- if (!equal(currentRoleIds, newRoleIds)) {
59
+ const setUserRoles = useCallback((roles: string[] | undefined) => {
60
+ if (!equal(userRoles, roles)) {
63
61
  _setUserRoles(roles);
64
62
  }
65
63
  }, [userRoles]);
@@ -299,7 +297,7 @@ export const useFirebaseAuthController = <USER extends FirebaseUserWrapper = any
299
297
  const firebaseUserWrapper: FirebaseUserWrapper | null = loggedUser
300
298
  ? {
301
299
  ...loggedUser,
302
- roles: userRoles?.map(r => r.id), // User.roles is string[], keep Role[] internally only
300
+ roles: userRoles,
303
301
  firebaseUser: loggedUser
304
302
  }
305
303
  : null;
@@ -1,6 +1,6 @@
1
1
  import { ApplicationVerifier, ConfirmationResult, User as FirebaseUser } from "@firebase/auth";
2
2
 
3
- import { AuthController, Role, User } from "@rebasepro/types";
3
+ import type { AuthController, User } from "@rebasepro/types";
4
4
 
5
5
  /**
6
6
  * @group Firebase
@@ -69,6 +69,6 @@ export type FirebaseAuthController<USER extends User = FirebaseUserWrapper, Extr
69
69
 
70
70
  setUser: (user: USER | null) => void;
71
71
 
72
- setUserRoles: (roles: Role[]) => void;
72
+ setUserRoles: (roles: string[]) => void;
73
73
 
74
74
  };
@@ -117,8 +117,10 @@ function normalizePropertiesEnumValues(
117
117
  );
118
118
  }
119
119
 
120
+ const propType = normalizedProperty.type ?? normalizedProperty.dataType;
121
+
120
122
  // Handle array properties with enum values in "of"
121
- if (normalizedProperty.dataType === "array" && typeof normalizedProperty.of === "object" && normalizedProperty.of !== null) {
123
+ if (propType === "array" && typeof normalizedProperty.of === "object" && normalizedProperty.of !== null) {
122
124
  const ofProp = normalizedProperty.of as Record<string, unknown>;
123
125
  if (ofProp.enum) {
124
126
  normalizedProperty.of = {
@@ -132,7 +134,7 @@ function normalizePropertiesEnumValues(
132
134
  }
133
135
 
134
136
  // Handle map properties recursively
135
- if (normalizedProperty.dataType === "map" && normalizedProperty.properties) {
137
+ if (propType === "map" && normalizedProperty.properties) {
136
138
  normalizedProperty.properties = normalizePropertiesEnumValues(
137
139
  normalizedProperty.properties as Properties,
138
140
  sortObjectFormat
@@ -253,7 +253,7 @@ export function buildRebaseSearchController(
253
253
  }
254
254
 
255
255
  try {
256
- const collection = await (typesenseClient as Record<string, Function>).collections(collectionName).retrieve();
256
+ const collection = await (typesenseClient as Record<string, (...args: any[]) => any>).collections(collectionName).retrieve();
257
257
 
258
258
  // Extract string fields from the schema
259
259
  const stringFields = (collection.fields as Array<{ type: string; name: string }>)
@@ -335,7 +335,7 @@ export function buildRebaseSearchController(
335
335
  searchParams.filter_by = parentFilter;
336
336
  }
337
337
 
338
- const result = await (typesenseClient as Record<string, Function>)
338
+ const result = await (typesenseClient as Record<string, (...args: any[]) => any>)
339
339
  .collections(collectionName)
340
340
  .documents()
341
341
  .search(searchParams);
@@ -1,6 +0,0 @@
1
- export declare const googleIcon: (mode: "light" | "dark") => import("react/jsx-runtime").JSX.Element;
2
- export declare const appleIcon: (mode: "light" | "dark") => import("react/jsx-runtime").JSX.Element;
3
- export declare const githubIcon: (mode: "light" | "dark") => import("react/jsx-runtime").JSX.Element;
4
- export declare const facebookIcon: (mode: "light" | "dark") => import("react/jsx-runtime").JSX.Element;
5
- export declare const microsoftIcon: (mode: "light" | "dark") => import("react/jsx-runtime").JSX.Element;
6
- export declare const twitterIcon: (mode: "light" | "dark") => import("react/jsx-runtime").JSX.Element;
@@ -1,135 +0,0 @@
1
- export const googleIcon = (mode: "light" | "dark") => <>
2
- <svg
3
- xmlns="http://www.w3.org/2000/svg"
4
- viewBox="0 0 64 64"
5
- width={32}
6
- height={32}
7
- >
8
- <linearGradient
9
- id="95yY7w43Oj6n2vH63j6HJb"
10
- x1="29.401"
11
- x2="29.401"
12
- y1="4.064"
13
- y2="106.734"
14
- gradientTransform="matrix(1 0 0 -1 0 66)"
15
- gradientUnits="userSpaceOnUse"
16
- >
17
- <stop offset="0" stopColor="#ff5840"/>
18
- <stop offset=".007" stopColor="#ff5840"/>
19
- <stop offset=".989" stopColor="#fa528c"/>
20
- <stop offset="1" stopColor="#fa528c"/>
21
- </linearGradient>
22
- <path
23
- fill="url(#95yY7w43Oj6n2vH63j6HJb)"
24
- d="M47.46,15.5l-1.37,1.48c-1.34,1.44-3.5,1.67-5.15,0.6c-2.71-1.75-6.43-3.13-11-2.37 c-4.94,0.83-9.17,3.85-11.64, 7.97l-8.03-6.08C14.99,9.82,23.2,5,32.5,5c5,0,9.94,1.56,14.27,4.46 C48.81,10.83,49.13,13.71,47.46,15.5z"
25
- />
26
- <linearGradient
27
- id="95yY7w43Oj6n2vH63j6HJc"
28
- x1="12.148"
29
- x2="12.148"
30
- y1=".872"
31
- y2="47.812"
32
- gradientTransform="matrix(1 0 0 -1 0 66)"
33
- gradientUnits="userSpaceOnUse"
34
- >
35
- <stop offset="0" stopColor="#feaa53"/>
36
- <stop offset=".612" stopColor="#ffcd49"/>
37
- <stop offset="1" stopColor="#ffde44"/>
38
- </linearGradient>
39
- <path
40
- fill="url(#95yY7w43Oj6n2vH63j6HJc)"
41
- d="M16.01,30.91c-0.09,2.47,0.37,4.83,1.27,6.96l-8.21,6.05c-1.35-2.51-2.3-5.28-2.75-8.22 c-1.06-6.88,0.54-13.38, 3.95-18.6l8.03,6.08C16.93,25.47,16.1,28.11,16.01,30.91z"
42
- />
43
- <linearGradient
44
- id="95yY7w43Oj6n2vH63j6HJd"
45
- x1="29.76"
46
- x2="29.76"
47
- y1="32.149"
48
- y2="-6.939"
49
- gradientTransform="matrix(1 0 0 -1 0 66)"
50
- gradientUnits="userSpaceOnUse"
51
- >
52
- <stop offset="0" stopColor="#42d778"/>
53
- <stop offset=".428" stopColor="#3dca76"/>
54
- <stop offset="1" stopColor="#34b171"/>
55
- </linearGradient>
56
- <path
57
- fill="url(#95yY7w43Oj6n2vH63j6HJd)"
58
- d="M50.45,51.28c-4.55,4.07-10.61,6.57-17.36,6.71C22.91,58.2,13.66,52.53,9.07,43.92l8.21-6.05 C19.78,43.81, 25.67,48,32.5,48c3.94,0,7.52-1.28,10.33-3.44L50.45,51.28z"
59
- />
60
- <linearGradient
61
- id="95yY7w43Oj6n2vH63j6HJe"
62
- x1="46"
63
- x2="46"
64
- y1="3.638"
65
- y2="35.593"
66
- gradientTransform="matrix(1 0 0 -1 0 66)"
67
- gradientUnits="userSpaceOnUse"
68
- >
69
- <stop offset="0" stopColor="#155cde"/>
70
- <stop offset=".278" stopColor="#1f7fe5"/>
71
- <stop offset=".569" stopColor="#279ceb"/>
72
- <stop offset=".82" stopColor="#2cafef"/>
73
- <stop offset="1" stopColor="#2eb5f0"/>
74
- </linearGradient>
75
- <path
76
- fill="url(#95yY7w43Oj6n2vH63j6HJe)"
77
- d="M59,31.97c0.01,7.73-3.26,14.58-8.55,19.31l-7.62-6.72c2.1-1.61,3.77-3.71,4.84-6.15
78
- c0.29-0.66-0.2-1.41-0.92-1.41H37c-2.21,0-4-1.79-4-4v-2c0-2.21,1.79-4,4-4h17C56.75,27,59,29.22,59,31.97z"
79
- />
80
- </svg>
81
- </>;
82
-
83
- export const appleIcon = (mode: "light" | "dark") => <svg width={32} height={32}
84
- viewBox="0 0 56 56"
85
- style={{ transform: "scale(2.8)" }}
86
- version="1.1"
87
- xmlns="http://www.w3.org/2000/svg">
88
- <g stroke={mode === "light" ? "#424245" : "white"} strokeWidth="0.5"
89
- fillRule="evenodd">
90
- <path
91
- d="M28.2226562,20.3846154 C29.0546875,20.3846154 30.0976562,19.8048315 30.71875,19.0317864 C31.28125,18.3312142 31.6914062,17.352829 31.6914062,16.3744437 C31.6914062,16.2415766 31.6796875,16.1087095 31.65625,16 C30.7304687,16.0362365 29.6171875,16.640178 28.9492187,17.4494596 C28.421875,18.06548 27.9414062,19.0317864 27.9414062,20.0222505 C27.9414062,20.1671964 27.9648438,20.3121424 27.9765625,20.3604577 C28.0351562,20.3725366 28.1289062,20.3846154 28.2226562,20.3846154 Z M25.2929688,35 C26.4296875,35 26.9335938,34.214876 28.3515625,34.214876 C29.7929688,34.214876 30.109375,34.9758423 31.375,34.9758423 C32.6171875,34.9758423 33.4492188,33.792117 34.234375,32.6325493 C35.1132812,31.3038779 35.4765625,29.9993643 35.5,29.9389701 C35.4179688,29.9148125 33.0390625,28.9122695 33.0390625,26.0979021 C33.0390625,23.6579784 34.9140625,22.5588048 35.0195312,22.474253 C33.7773438,20.6382708 31.890625,20.5899555 31.375,20.5899555 C29.9804688,20.5899555 28.84375,21.4596313 28.1289062,21.4596313 C27.3554688,21.4596313 26.3359375,20.6382708 25.1289062,20.6382708 C22.8320312,20.6382708 20.5,22.5950413 20.5,26.2911634 C20.5,28.5861411 21.3671875,31.013986 22.4335938,32.5842339 C23.3476562,33.9129053 24.1445312,35 25.2929688,35 Z"
92
- fill={mode === "light" ? "#424245" : "white"} fillRule="nonzero"/>
93
- </g>
94
- </svg>;
95
-
96
- export const githubIcon = (mode: "light" | "dark") => <svg
97
- fill={mode === "light" ? "#1c1e21" : "white"}
98
- role="img"
99
- viewBox="0 0 24 24"
100
- width={28}
101
- height={28}
102
- xmlns="http://www.w3.org/2000/svg">
103
- <path
104
- d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
105
- </svg>;
106
-
107
-
108
- export const facebookIcon = (mode: "light" | "dark") => <svg
109
- xmlns="http://www.w3.org/2000/svg"
110
- width={28} height={28}
111
- viewBox="0 0 90 90">
112
- <g>
113
- <path
114
- d="M90,15.001C90,7.119,82.884,0,75,0H15C7.116,0,0,7.119,0,15.001v59.998 C0,82.881,7.116,90,15.001,90H45V56H34V41h11v-5.844C45,25.077,52.568,16,61.875,16H74v15H61.875C60.548,31,59,32.611,59,35.024V41 h15v15H59v34h16c7.884,0,15-7.119,15-15.001V15.001z"
115
- fill={mode === "light" ? "#39569c" : "white"}/>
116
- </g>
117
- </svg>;
118
-
119
- export const microsoftIcon = (mode: "light" | "dark") => <svg
120
- xmlns="http://www.w3.org/2000/svg" width={28} height={28}
121
- viewBox="0 0 480 480">
122
- <g>
123
- <path
124
- d="M0.176,224L0.001,67.963l192-26.072V224H0.176z M224.001,37.241L479.937,0v224H224.001V37.241z M479.999,256l-0.062,224 l-255.936-36.008V256H479.999z M192.001,439.918L0.157,413.621L0.147,256h191.854V439.918z"
125
- fill={mode === "light" ? "#00a2ed" : "white"}/>
126
- </g>
127
- </svg>;
128
-
129
- export const twitterIcon = (mode: "light" | "dark") => <svg
130
- xmlns="http://www.w3.org/2000/svg" width={28} height={28}
131
- viewBox="0 0 24 24">
132
- <path fill={mode === "light" ? "#00acee" : "white"}
133
- d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/>
134
- </svg>;
135
-