@rebasepro/firebase 0.22.0 → 0.23.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.
@@ -56,6 +56,33 @@ export declare function resolveOffsetWindow(limit: number | undefined, offset: n
56
56
  fetchLimit: number | undefined;
57
57
  skip: number;
58
58
  };
59
+ /**
60
+ * The rows for the ids a text search returned, read once: in the order the
61
+ * search ranked them, windowed by `limit` and `offset`. An id whose document is
62
+ * gone is left out.
63
+ */
64
+ export declare function readSearchResults({ ids, limit, offset, readOne }: {
65
+ ids: readonly string[];
66
+ limit?: number;
67
+ offset?: number;
68
+ readOne: (id: string) => Promise<Record<string, unknown> | undefined>;
69
+ }): Promise<Record<string, unknown>[]>;
70
+ /**
71
+ * The rows for the ids a text search returned, kept live: one document
72
+ * listener per id in the `limit`/`offset` window, and every change delivered
73
+ * as the whole list, in the order the search ranked the ids.
74
+ *
75
+ * The returned function cancels all of it, a search still in flight included:
76
+ * its listeners are then never opened.
77
+ */
78
+ export declare function listenToSearchResults({ ids, limit, offset, listenOne, onUpdate, onError }: {
79
+ ids: Promise<readonly string[] | undefined>;
80
+ limit?: number;
81
+ offset?: number;
82
+ listenOne: (id: string, onRow: (row: Record<string, unknown> | null) => void, onError?: (error: Error) => void) => () => void;
83
+ onUpdate: (rows: Record<string, unknown>[]) => void;
84
+ onError?: (error: Error) => void;
85
+ }): () => void;
59
86
  /**
60
87
  * Use this hook to build a {@link DataDriver} based on Firestore
61
88
  * @param firebaseApp
package/dist/index.es.js CHANGED
@@ -9,7 +9,7 @@ import { COLLECTION_PATH_SEPARATOR, buildRebaseData, normalizeDriverOrderBy, sor
9
9
  import { DocumentReference, GeoPoint as GeoPoint$1, Timestamp, VectorValue, collection, deleteDoc, deleteField, doc, getCountFromServer, getDoc, getDocs, getFirestore, limit, onSnapshot, orderBy, query, serverTimestamp, setDoc, startAfter, vector, where } from "firebase/firestore";
10
10
  import Fuse from "fuse.js";
11
11
  import { getFunctions, httpsCallable } from "firebase/functions";
12
- import { endAt, equalTo, get, getDatabase, limitToFirst, onValue, orderByChild, orderByKey, push, query as query$1, ref as ref$1, remove, set, startAfter as startAfter$1, startAt } from "firebase/database";
12
+ import { endAt, equalTo, get, getDatabase, limitToFirst, onValue, orderByChild, orderByKey, push, query as query$1, ref as ref$1, remove, set, startAfter as startAfter$1, startAt, update } from "firebase/database";
13
13
  import { removeUndefined } from "@rebasepro/utils";
14
14
  import { AdminModeControllerProvider, ErrorView, ModeControllerProvider, Rebase, RebaseLogo, RebaseRoutes, SnackbarProvider, useBrowserTitleAndIcon, useBuildAdminModeController, useBuildLocalConfigurationPersistence, useBuildModeController, useModeController, useSnackbarController } from "@rebasepro/app";
15
15
  import { AppBar, CollectionRegistryContext, Drawer, NavigationStateContext, RebaseRoute, Scaffold, SideDialogs, SidePanelProvider, UrlContext, useBuildCollectionRegistryController, useBuildNavigationStateController, useBuildUrlController } from "@rebasepro/cms";
@@ -533,7 +533,10 @@ var docsToCollectionTree = (docs) => {
533
533
  if (id.includes(COLLECTION_PATH_SEPARATOR)) {
534
534
  const parentId = id.split(COLLECTION_PATH_SEPARATOR).slice(0, -1).join(COLLECTION_PATH_SEPARATOR);
535
535
  const parentCollection = collectionsMap[parentId];
536
- if (parentCollection) parentCollection.subcollections = () => [...parentCollection.subcollections?.() ?? [], collection];
536
+ if (parentCollection) {
537
+ const siblings = parentCollection.subcollections;
538
+ parentCollection.subcollections = () => [...siblings?.() ?? [], collection];
539
+ }
537
540
  delete collectionsMap[id];
538
541
  }
539
542
  });
@@ -984,6 +987,53 @@ function resolveOffsetWindow(limit, offset) {
984
987
  };
985
988
  }
986
989
  /**
990
+ * The rows for the ids a text search returned, read once: in the order the
991
+ * search ranked them, windowed by `limit` and `offset`. An id whose document is
992
+ * gone is left out.
993
+ */
994
+ async function readSearchResults({ ids, limit, offset, readOne }) {
995
+ const { fetchLimit, skip } = resolveOffsetWindow(limit, offset);
996
+ return (await Promise.all(ids.slice(skip, fetchLimit).map(readOne))).filter((row) => row !== void 0);
997
+ }
998
+ /**
999
+ * The rows for the ids a text search returned, kept live: one document
1000
+ * listener per id in the `limit`/`offset` window, and every change delivered
1001
+ * as the whole list, in the order the search ranked the ids.
1002
+ *
1003
+ * The returned function cancels all of it, a search still in flight included:
1004
+ * its listeners are then never opened.
1005
+ */
1006
+ function listenToSearchResults({ ids, limit, offset, listenOne, onUpdate, onError }) {
1007
+ let cancelled = false;
1008
+ let subscriptions = [];
1009
+ ids.then((found) => {
1010
+ if (cancelled) return;
1011
+ const { fetchLimit, skip } = resolveOffsetWindow(limit, offset);
1012
+ const windowIds = (found ?? []).slice(skip, fetchLimit);
1013
+ if (windowIds.length === 0) {
1014
+ onUpdate([]);
1015
+ return;
1016
+ }
1017
+ const rows = /* @__PURE__ */ new Map();
1018
+ const emit = () => onUpdate(windowIds.flatMap((id) => {
1019
+ const row = rows.get(id);
1020
+ return row ? [row] : [];
1021
+ }));
1022
+ subscriptions = windowIds.map((id) => listenOne(id, (row) => {
1023
+ if (row) rows.set(id, row);
1024
+ else rows.delete(id);
1025
+ emit();
1026
+ }, onError));
1027
+ }).catch((error) => {
1028
+ if (cancelled) return;
1029
+ onError?.(error instanceof Error ? error : new Error(String(error)));
1030
+ });
1031
+ return () => {
1032
+ cancelled = true;
1033
+ subscriptions.forEach((unsubscribe) => unsubscribe());
1034
+ };
1035
+ }
1036
+ /**
987
1037
  * Use this hook to build a {@link DataDriver} based on Firestore
988
1038
  * @param firebaseApp
989
1039
  * @param textSearchControllerBuilder
@@ -1044,11 +1094,11 @@ function useFirestoreDriver({ firebaseApp, textSearchControllerBuilder, firestor
1044
1094
  error: onError
1045
1095
  });
1046
1096
  }, [firebaseApp]);
1047
- const performTextSearch = useCallback(({ path, databaseId, searchString, onUpdate }) => {
1097
+ /** The ids the text search controller finds for `searchString` under `path`. */
1098
+ const searchIds = useCallback((path, searchString, databaseId) => {
1048
1099
  if (!firebaseApp) throw Error("useFirestoreDriver Firebase not initialised");
1049
1100
  const textSearchController = searchControllerRef.current;
1050
1101
  if (!textSearchController) throw Error("Trying to make text search without specifying a FirestoreTextSearchController");
1051
- let subscriptions = [];
1052
1102
  const currentUser = getAuth(firebaseApp)?.currentUser;
1053
1103
  const search = textSearchController.search({
1054
1104
  path,
@@ -1057,37 +1107,24 @@ function useFirestoreDriver({ firebaseApp, textSearchControllerBuilder, firestor
1057
1107
  databaseId
1058
1108
  });
1059
1109
  if (!search) throw Error("The current path is not supported by the specified FirestoreTextSearchController");
1060
- search.then((ids) => {
1061
- if (!ids || ids.length === 0) {
1062
- subscriptions = [];
1063
- onUpdate([]);
1064
- }
1065
- const rows = [];
1066
- const addedEntitiesSet = /* @__PURE__ */ new Set();
1067
- subscriptions = (ids ?? []).map((id) => {
1068
- return listenOne({
1069
- path,
1070
- id,
1071
- onUpdate: (row) => {
1072
- const incomingId = row?.id;
1073
- if (row && incomingId !== void 0) {
1074
- if (!addedEntitiesSet.has(incomingId)) {
1075
- addedEntitiesSet.add(incomingId);
1076
- rows.push(row);
1077
- onUpdate(rows);
1078
- }
1079
- } else {
1080
- addedEntitiesSet.delete(id);
1081
- onUpdate([...rows.filter((r) => r.id !== id)]);
1082
- }
1083
- }
1084
- });
1085
- });
1110
+ return search;
1111
+ }, [firebaseApp]);
1112
+ const performTextSearch = useCallback(({ path, collection, searchString, limit, offset, onUpdate, onError }) => {
1113
+ return listenToSearchResults({
1114
+ ids: searchIds(path, searchString, collection?.databaseId),
1115
+ limit,
1116
+ offset,
1117
+ listenOne: (id, onRow, onRowError) => listenOne({
1118
+ path,
1119
+ id,
1120
+ collection,
1121
+ onUpdate: onRow,
1122
+ onError: onRowError
1123
+ }),
1124
+ onUpdate,
1125
+ onError
1086
1126
  });
1087
- return () => {
1088
- subscriptions.forEach((p) => p());
1089
- };
1090
- }, [firebaseApp, listenOne]);
1127
+ }, [searchIds, listenOne]);
1091
1128
  const initTextSearch = useCallback(async (props) => {
1092
1129
  console.debug("Init text search controller", searchControllerRef.current, props.path);
1093
1130
  if (!searchControllerRef.current) {
@@ -1128,9 +1165,19 @@ function useFirestoreDriver({ firebaseApp, textSearchControllerBuilder, firestor
1128
1165
  orderBy,
1129
1166
  order
1130
1167
  });
1168
+ if (searchString) return readSearchResults({
1169
+ ids: await searchIds(resolvedPath, searchString, databaseId) ?? [],
1170
+ limit,
1171
+ offset,
1172
+ readOne: (id) => getAndBuildEntity(resolvedPath, id, databaseId)
1173
+ });
1131
1174
  const { fetchLimit, skip } = resolveOffsetWindow(limit, offset);
1132
1175
  return (await getDocs(buildQuery(resolvedPath, filter, orderBy, order, startAfter, fetchLimit, databaseId))).docs.slice(skip).map((doc) => createRowFromDocument(doc));
1133
- }, [buildQuery]);
1176
+ }, [
1177
+ buildQuery,
1178
+ searchIds,
1179
+ getAndBuildEntity
1180
+ ]);
1134
1181
  /**
1135
1182
  * Listen to a entities in a given path
1136
1183
  * @param path
@@ -1147,7 +1194,7 @@ function useFirestoreDriver({ firebaseApp, textSearchControllerBuilder, firestor
1147
1194
  * @see useCollection if you need this functionality implemented as a hook
1148
1195
  * @group Firestore
1149
1196
  */
1150
- const listenCollection = useCallback(({ path, filter, limit, startAfter, searchString, orderBy, order, onUpdate, onError, collection }) => {
1197
+ const listenCollection = useCallback(({ path, filter, limit, offset, startAfter, searchString, orderBy, order, onUpdate, onError, collection }) => {
1151
1198
  console.debug("Listening collection", {
1152
1199
  path,
1153
1200
  searchString,
@@ -1162,18 +1209,22 @@ function useFirestoreDriver({ firebaseApp, textSearchControllerBuilder, firestor
1162
1209
  const databaseId = collection?.databaseId;
1163
1210
  if (searchString) return performTextSearch({
1164
1211
  path,
1212
+ collection,
1165
1213
  searchString,
1214
+ limit,
1215
+ offset,
1166
1216
  onUpdate,
1167
- databaseId
1217
+ onError
1168
1218
  });
1169
1219
  const resolvedPath = path;
1170
1220
  console.debug("Resolved path for listening", {
1171
1221
  path,
1172
1222
  resolvedPath
1173
1223
  });
1174
- return onSnapshot(buildQuery(resolvedPath, filter, orderBy, order, startAfter, limit, databaseId), {
1224
+ const { fetchLimit, skip } = resolveOffsetWindow(limit, offset);
1225
+ return onSnapshot(buildQuery(resolvedPath, filter, orderBy, order, startAfter, fetchLimit, databaseId), {
1175
1226
  next: (entity) => {
1176
- if (!searchString) onUpdate(entity.docs.map((doc) => createRowFromDocument(doc)));
1227
+ onUpdate(entity.docs.slice(skip).map((doc) => createRowFromDocument(doc)));
1177
1228
  },
1178
1229
  error: onError
1179
1230
  });
@@ -1267,11 +1318,17 @@ function useFirestoreDriver({ firebaseApp, textSearchControllerBuilder, firestor
1267
1318
  if (value === void 0 || value === null) return Promise.resolve(true);
1268
1319
  return (await getDocs(query(collection(firestore, path), where(name, "==", rebaseToFirestoreModel(value, firestore))))).docs.filter((doc) => doc.id !== id).length === 0;
1269
1320
  }, [firebaseApp]);
1270
- const count = useCallback(async ({ path, filter, order, orderBy, collection }) => {
1321
+ const count = useCallback(async ({ path, filter, order, orderBy, searchString, collection }) => {
1271
1322
  if (!firebaseApp) throw Error("useFirestoreDriver Firebase not initialised");
1272
1323
  const databaseId = collection?.databaseId;
1273
- return (await getCountFromServer(buildQuery(path, filter, orderBy, order, void 0, void 0, databaseId))).data().count;
1274
- }, [firebaseApp]);
1324
+ const resolvedPath = path;
1325
+ if (searchString) return (await searchIds(resolvedPath, searchString, databaseId) ?? []).length;
1326
+ return (await getCountFromServer(buildQuery(resolvedPath, filter, orderBy, order, void 0, void 0, databaseId))).data().count;
1327
+ }, [
1328
+ firebaseApp,
1329
+ buildQuery,
1330
+ searchIds
1331
+ ]);
1275
1332
  const isFilterCombinationValid = useCallback(({ path, collection, filterValues, sortBy }) => {
1276
1333
  if (!firebaseApp) throw Error("useFirestoreDriver Firebase not initialised");
1277
1334
  if (firestoreIndexesBuilder === void 0) return true;
@@ -1374,7 +1431,7 @@ function getCMSPathFromFirestorePath(fsPath) {
1374
1431
  return fsPath.substring(0, to);
1375
1432
  }
1376
1433
  function rebaseToFirestoreModel(data, firestore, inArray = false) {
1377
- if (data === void 0) return deleteField();
1434
+ if (data === void 0) return inArray ? void 0 : deleteField();
1378
1435
  else if (data === null) return null;
1379
1436
  else if (Array.isArray(data)) return data.filter((v) => v !== void 0).map((v) => rebaseToFirestoreModel(v, firestore, true));
1380
1437
  else if (typeof data === "object" && data !== null && "isEntityReference" in data && typeof data.isEntityReference === "function" && data.isEntityReference()) {
@@ -1387,7 +1444,7 @@ function rebaseToFirestoreModel(data, firestore, inArray = false) {
1387
1444
  else if (data instanceof Date) return Timestamp.fromDate(data);
1388
1445
  else if (data && typeof data === "object" && "__type__" in data && data.__type__ === "__vector__") return vector(data.value || []);
1389
1446
  else if (data && typeof data === "object") return Object.entries(data).map(([key, v]) => {
1390
- const firestoreModel = rebaseToFirestoreModel(v, firestore);
1447
+ const firestoreModel = rebaseToFirestoreModel(v, firestore, inArray);
1391
1448
  if (firestoreModel !== void 0) return { [key]: firestoreModel };
1392
1449
  else return {};
1393
1450
  }).reduce((a, b) => ({
@@ -1492,6 +1549,25 @@ function rtdbConstraints(plan) {
1492
1549
  if (plan.limitToFirst !== void 0) constraints.push(limitToFirst(plan.limitToFirst));
1493
1550
  return constraints;
1494
1551
  }
1552
+ /**
1553
+ * The rows of a query result, in the query's order, with the first `skip` dropped.
1554
+ *
1555
+ * `snapshot.val()` is a plain object, and an object's keys come back in key
1556
+ * order (integer-like keys first), not in the order the query sorted the
1557
+ * children. Read that way, `orderBy` was lost and an offset page dropped rows
1558
+ * by key rather than by position — page two of a list ordered by `age` held
1559
+ * whichever rows sorted last by id. `forEach` walks the children in query order.
1560
+ */
1561
+ function rowsFromSnapshot(snapshot, skip) {
1562
+ const rows = [];
1563
+ snapshot.forEach((child) => {
1564
+ rows.push({
1565
+ ...delegateToCMSModel(child.val()),
1566
+ id: child.key
1567
+ });
1568
+ });
1569
+ return rows.slice(skip);
1570
+ }
1495
1571
  function useFirebaseRTDBDelegate({ firebaseApp }) {
1496
1572
  return {
1497
1573
  key: "firebase_rtdb",
@@ -1499,27 +1575,14 @@ function useFirebaseRTDBDelegate({ firebaseApp }) {
1499
1575
  if (!firebaseApp) throw new Error("Firebase app not provided");
1500
1576
  const database = getDatabase(firebaseApp);
1501
1577
  const plan = planRTDBQuery(props);
1502
- const entity = await get(query$1(ref$1(database, props.path), ...rtdbConstraints(plan)));
1503
- if (entity.exists()) return Object.entries(entity.val()).slice(plan.skip ?? 0).map(([id, values]) => ({
1504
- ...delegateToCMSModel(values),
1505
- id
1506
- }));
1507
- return [];
1578
+ return rowsFromSnapshot(await get(query$1(ref$1(database, props.path), ...rtdbConstraints(plan))), plan.skip ?? 0);
1508
1579
  }, [firebaseApp]),
1509
1580
  listenCollection: useCallback((props) => {
1510
1581
  if (!firebaseApp) throw new Error("Firebase app not provided");
1511
1582
  const database = getDatabase(firebaseApp);
1512
1583
  const { onUpdate, onError } = props;
1513
1584
  const plan = planRTDBQuery(props);
1514
- const unsubscribe = onValue(query$1(ref$1(database, props.path), ...rtdbConstraints(plan)), (entity) => {
1515
- if (entity.exists()) {
1516
- const result = Object.entries(entity.val()).slice(plan.skip ?? 0).map(([id, values]) => ({
1517
- ...delegateToCMSModel(values),
1518
- id
1519
- }));
1520
- onUpdate(result);
1521
- } else onUpdate([]);
1522
- }, (error) => onError?.(error));
1585
+ const unsubscribe = onValue(query$1(ref$1(database, props.path), ...rtdbConstraints(plan)), (entity) => onUpdate(rowsFromSnapshot(entity, plan.skip ?? 0)), (error) => onError?.(error));
1523
1586
  return () => unsubscribe();
1524
1587
  }, [firebaseApp]),
1525
1588
  fetchOne: useCallback(async ({ path, id }) => {
@@ -1533,21 +1596,22 @@ function useFirebaseRTDBDelegate({ firebaseApp }) {
1533
1596
  listenOne: useCallback(({ path, id, onUpdate, onError }) => {
1534
1597
  if (!firebaseApp) throw new Error("Firebase app not provided");
1535
1598
  const unsubscribe = onValue(ref$1(getDatabase(firebaseApp), `${path}/${id}`), (entity) => {
1536
- if (entity.exists()) onUpdate({
1599
+ onUpdate(entity.exists() ? {
1537
1600
  ...delegateToCMSModel(entity.val()),
1538
1601
  id
1539
- });
1540
- else onError?.(/* @__PURE__ */ new Error("Entity does not exist"));
1541
- });
1602
+ } : null);
1603
+ }, (error) => onError?.(error));
1542
1604
  return () => unsubscribe();
1543
1605
  }, [firebaseApp]),
1544
- save: useCallback(async ({ path, id, values }) => {
1606
+ save: useCallback(async ({ path, id, values, status }) => {
1545
1607
  if (!firebaseApp) throw new Error("Firebase app not provided");
1546
1608
  const database = getDatabase(firebaseApp);
1547
1609
  const finalId = id ?? push(ref$1(database, path)).key;
1548
1610
  if (!finalId) throw new Error("Could not generate a new id");
1549
- const transformedValues = cmsToRTDBModel(values, database);
1550
- await set(ref$1(database, `${path}/${finalId}`), transformedValues);
1611
+ const transformedValues = cmsToRTDBRecord(values, database);
1612
+ const rowRef = ref$1(database, `${path}/${finalId}`);
1613
+ if (status === "existing") await update(rowRef, transformedValues);
1614
+ else await set(rowRef, transformedValues);
1551
1615
  return {
1552
1616
  ...values,
1553
1617
  id: finalId
@@ -1559,11 +1623,19 @@ function useFirebaseRTDBDelegate({ firebaseApp }) {
1559
1623
  }, [firebaseApp]),
1560
1624
  checkUniqueField: useCallback(async (slug, name, value, id) => {
1561
1625
  if (!firebaseApp) throw new Error("Firebase app not provided");
1562
- const entity = await get(query$1(ref$1(getDatabase(firebaseApp), slug), orderByChild(name), startAt(value), limitToFirst(1)));
1563
- if (!entity.exists()) return true;
1564
- const [key, entityValue] = Object.entries(entity.val())[0];
1565
- if (entityValue && typeof entityValue === "object" && entityValue[name] === value && key === id) return true;
1566
- return false;
1626
+ const database = getDatabase(firebaseApp);
1627
+ const stored = cmsToRTDBModel(value, database);
1628
+ if (stored === null) return true;
1629
+ if (!isRTDBValue(stored)) throw new Error(`${RTDB}: cannot check \`${name}\` for uniqueness by a ${Array.isArray(stored) ? "array" : typeof stored} value; the Realtime Database compares strings, numbers and booleans.`);
1630
+ const matches = await get(query$1(ref$1(database, slug), orderByChild(name), equalTo(stored), limitToFirst(2)));
1631
+ let unique = true;
1632
+ matches.forEach((child) => {
1633
+ if (id === void 0 || child.key !== String(id)) {
1634
+ unique = false;
1635
+ return true;
1636
+ }
1637
+ });
1638
+ return unique;
1567
1639
  }, [firebaseApp]),
1568
1640
  isFilterCombinationValid: useCallback(({ path, filter, sortBy }) => {
1569
1641
  return false;
@@ -1600,16 +1672,15 @@ function cmsToRTDBModel(data, database) {
1600
1672
  const entityRef = data;
1601
1673
  return ref$1(database, `${entityRef.slug}/${entityRef.id}`);
1602
1674
  } else if (data instanceof Date) return data.toISOString();
1603
- else if (data && typeof data === "object") return Object.entries(data).map(([key, v]) => {
1604
- const rtdbModel = cmsToRTDBModel(v, database);
1605
- if (rtdbModel !== void 0) return { [key]: rtdbModel };
1606
- else return {};
1607
- }).reduce((a, b) => ({
1608
- ...a,
1609
- ...b
1610
- }), {});
1675
+ else if (data && typeof data === "object") return cmsToRTDBRecord(data, database);
1611
1676
  return data;
1612
1677
  }
1678
+ /** {@link cmsToRTDBModel} for a map of values: each child converted, keys kept. */
1679
+ function cmsToRTDBRecord(data, database) {
1680
+ const result = {};
1681
+ for (const [key, v] of Object.entries(data)) result[key] = cmsToRTDBModel(v, database);
1682
+ return result;
1683
+ }
1613
1684
  //#endregion
1614
1685
  //#region src/hooks/useRecaptcha.tsx
1615
1686
  var RECAPTCHA_CONTAINER_ID = "recaptcha-container";
@@ -2789,6 +2860,6 @@ function RebaseFirebaseApp({ name, logo, logoDark, accessGate, collections, view
2789
2860
  }) });
2790
2861
  }
2791
2862
  //#endregion
2792
- export { FirebaseLoginView, LoginButton, RECAPTCHA_CONTAINER_ID, RebaseFirebaseApp, buildCollectionId, buildExternalSearchController, buildPineconeSearchController, buildRebaseSearchController, docToCollection, docsToCollectionTree, firestoreToRebaseModel, getFirestoreDataInPath, localSearchControllerBuilder, performAlgoliaTextSearch, performPineconeTextSearch, planRTDBQuery, rebaseToFirestoreModel, resolveAccessDecision, resolveOffsetWindow, resolveRoleRefresh, useAppCheck, useBuildUserManagement, useFirebaseAccessGate, useFirebaseAuthController, useFirebaseRTDBDelegate, useFirebaseStorageSource, useFirestoreDriver, useInitialiseFirebase, useRecaptcha };
2863
+ export { FirebaseLoginView, LoginButton, RECAPTCHA_CONTAINER_ID, RebaseFirebaseApp, buildCollectionId, buildExternalSearchController, buildPineconeSearchController, buildRebaseSearchController, docToCollection, docsToCollectionTree, firestoreToRebaseModel, getFirestoreDataInPath, listenToSearchResults, localSearchControllerBuilder, performAlgoliaTextSearch, performPineconeTextSearch, planRTDBQuery, readSearchResults, rebaseToFirestoreModel, resolveAccessDecision, resolveOffsetWindow, resolveRoleRefresh, useAppCheck, useBuildUserManagement, useFirebaseAccessGate, useFirebaseAuthController, useFirebaseRTDBDelegate, useFirebaseStorageSource, useFirestoreDriver, useInitialiseFirebase, useRecaptcha };
2793
2864
 
2794
2865
  //# sourceMappingURL=index.es.js.map