@hyper-fetch/firebase-admin 6.0.0 → 7.0.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,24 +1,24 @@
1
- import { CollectionReference, DocumentReference, DocumentSnapshot, Firestore, Query } from "firebase-admin/firestore";
2
- import { getSocketAdapterBindings } from "@hyper-fetch/sockets";
1
+ import {
2
+ CollectionReference,
3
+ DocumentReference,
4
+ DocumentSnapshot,
5
+ Firestore,
6
+ Query,
7
+ QuerySnapshot,
8
+ } from "firebase-admin/firestore";
9
+ import { SocketAdapter } from "@hyper-fetch/sockets";
3
10
 
4
11
  import { getGroupedResultFirestore, getOrderedResultFirestore, getRef, applyFireStoreAdminConstraints } from "./utils";
5
- import { getStatus } from "utils";
6
12
  import { FirestoreAdminSocketAdapterType } from "adapter";
13
+ import { getStatus } from "utils";
7
14
 
8
- export const firestoreAdminSockets = (database: Firestore): FirestoreAdminSocketAdapterType => {
9
- return (socket) => {
10
- const {
11
- open,
12
- connecting,
13
- reconnectionAttempts,
14
- listeners,
15
- removeListener,
16
- onReconnect,
17
- onListen,
18
- onEvent,
19
- onError,
20
- } = getSocketAdapterBindings(socket, { open: true });
21
-
15
+ export const firestoreAdminSockets = (database: Firestore) => {
16
+ return (
17
+ new SocketAdapter({
18
+ name: "firebase-admin-firestore",
19
+ defaultConnected: true,
20
+ }) as unknown as FirestoreAdminSocketAdapterType
21
+ ).setConnector(({ socket, onReconnect, onListen, onEvent, onError }) => {
22
22
  const connect = () => {
23
23
  throw new Error("Connect function is not implemented for Firestore Admin socket.");
24
24
  };
@@ -28,11 +28,11 @@ export const firestoreAdminSockets = (database: Firestore): FirestoreAdminSocket
28
28
  };
29
29
 
30
30
  const reconnect = () => {
31
- onReconnect(disconnect, connect);
31
+ onReconnect({ disconnect, connect });
32
32
  };
33
33
 
34
- const listen: ReturnType<FirestoreAdminSocketAdapterType>["listen"] = (listener, callback) => {
35
- const fullUrl = socket.url + listener.endpoint;
34
+ const listen: FirestoreAdminSocketAdapterType["listen"] = (listener, callback) => {
35
+ const fullUrl = socket.url + listener.topic;
36
36
  const { options } = listener;
37
37
  let pathRef: DocumentReference | Query = getRef(database, fullUrl);
38
38
  if (pathRef instanceof CollectionReference) {
@@ -44,20 +44,23 @@ export const firestoreAdminSockets = (database: Firestore): FirestoreAdminSocket
44
44
 
45
45
  unsubscribe = pathRef.onSnapshot(
46
46
  (snapshot) => {
47
- const getSnapshotData = (s) => (s.data() ? { ...s.data(), __key: s.id } : null);
47
+ const getSnapshotData = (s: DocumentSnapshot) => (s.data() ? { ...s.data(), __key: s.id } : null);
48
48
  const response =
49
- snapshot instanceof DocumentSnapshot ? getSnapshotData(snapshot) : getOrderedResultFirestore(snapshot);
49
+ snapshot instanceof DocumentSnapshot
50
+ ? getSnapshotData(snapshot)
51
+ : getOrderedResultFirestore(snapshot as QuerySnapshot);
50
52
  const status = getStatus(response);
51
- const groupedResult = options?.groupByChangeType === true ? getGroupedResultFirestore(snapshot) : null;
53
+ const groupedResult =
54
+ options?.groupByChangeType === true ? getGroupedResultFirestore(snapshot as QuerySnapshot) : null;
52
55
  const extra = { ref: pathRef, snapshot, unsubscribe, groupedResult, status };
53
56
  callback({ data: response, extra });
54
- onEvent(listener.endpoint, response, extra);
57
+ onEvent({ topic: listener.topic, data: response, extra });
55
58
  },
56
59
  (error) => {
57
- onError(error);
60
+ onError({ error });
58
61
  },
59
62
  );
60
- unmount = onListen(listener, callback, unsubscribe);
63
+ unmount = onListen({ listener, callback, onUnmount: unsubscribe });
61
64
  clearListeners = () => {
62
65
  unsubscribe();
63
66
  unmount();
@@ -71,16 +74,11 @@ export const firestoreAdminSockets = (database: Firestore): FirestoreAdminSocket
71
74
  };
72
75
 
73
76
  return {
74
- open,
75
- reconnectionAttempts,
76
- listeners,
77
- connecting,
78
- listen,
79
- removeListener,
80
- emit,
81
77
  connect,
82
78
  reconnect,
83
79
  disconnect,
80
+ emit,
81
+ listen,
84
82
  };
85
- };
83
+ });
86
84
  };
@@ -1,12 +1,9 @@
1
- import { CollectionReference } from "firebase-admin/lib/firestore";
1
+ import { Query } from "firebase-admin/firestore";
2
2
  import { OrderByDirection } from "firebase/firestore";
3
3
 
4
4
  import { FirestorePermittedMethods, FirestoreQueryConstraints, SharedQueryConstraints } from "../../constraints";
5
5
 
6
- export const applyFireStoreAdminConstraint = (
7
- collectionRef: CollectionReference,
8
- { type, values }: FirestorePermittedMethods,
9
- ) => {
6
+ export const applyFireStoreAdminConstraint = (collectionRef: Query, { type, values }: FirestorePermittedMethods) => {
10
7
  switch (type) {
11
8
  case FirestoreQueryConstraints.WHERE: {
12
9
  const [fieldPath, strOp, value] = values;
@@ -14,7 +11,7 @@ export const applyFireStoreAdminConstraint = (
14
11
  }
15
12
  case FirestoreQueryConstraints.ORDER_BY: {
16
13
  const [field, ord] = values;
17
- return collectionRef.orderBy(field, ord as OrderByDirection);
14
+ return collectionRef.orderBy(field!, ord as OrderByDirection);
18
15
  }
19
16
  case FirestoreQueryConstraints.LIMIT: {
20
17
  const [limitValue] = values;
@@ -41,10 +38,7 @@ export const applyFireStoreAdminConstraint = (
41
38
  }
42
39
  };
43
40
 
44
- export const applyFireStoreAdminConstraints = (
45
- collectionRef: CollectionReference,
46
- constraints: FirestorePermittedMethods[],
47
- ) => {
41
+ export const applyFireStoreAdminConstraints = (collectionRef: Query, constraints: FirestorePermittedMethods[]) => {
48
42
  return constraints.reduce((collection, constraint) => {
49
43
  return applyFireStoreAdminConstraint(collection, constraint);
50
44
  }, collectionRef);
@@ -1,4 +1,4 @@
1
- import { CollectionReference, DocumentReference, Firestore } from "firebase-admin/lib/firestore";
1
+ import { CollectionReference, DocumentReference, Firestore } from "firebase-admin/firestore";
2
2
 
3
3
  export const getRef = (db: Firestore, fullUrl: string) => {
4
4
  const withoutSurroundingSlashes = fullUrl.replace(/^\/|\/$/g, "");
@@ -6,14 +6,17 @@ export const getRef = (db: Firestore, fullUrl: string) => {
6
6
  return index % 2 === 0 ? ["collection", element] : ["doc", element];
7
7
  });
8
8
 
9
- return urlParts.reduce((_db, value) => {
10
- const [method, pathPart] = value;
11
- if (method === "doc" && "doc" in _db) {
12
- return _db.doc(pathPart);
13
- }
14
- if (method === "collection" && "collection" in _db) {
15
- return _db.collection(pathPart);
16
- }
17
- return _db;
18
- }, db as unknown as Firestore | CollectionReference | DocumentReference) as CollectionReference | DocumentReference;
9
+ return urlParts.reduce(
10
+ (_db, value) => {
11
+ const [method, pathPart] = value;
12
+ if (method === "doc" && "doc" in _db) {
13
+ return _db.doc(pathPart);
14
+ }
15
+ if (method === "collection" && "collection" in _db) {
16
+ return _db.collection(pathPart);
17
+ }
18
+ return _db;
19
+ },
20
+ db as unknown as Firestore | CollectionReference | DocumentReference,
21
+ ) as CollectionReference | DocumentReference;
19
22
  };
@@ -1,13 +1,19 @@
1
- export const getOrderedResultFirestore = (snapshot: any) => {
2
- const result = [];
1
+ import { QuerySnapshot, DocumentData } from "firebase-admin/firestore";
2
+
3
+ export const getOrderedResultFirestore = (snapshot: QuerySnapshot) => {
4
+ const result: (DocumentData & { __key: string })[] = [];
3
5
  snapshot.docs.forEach((d) => {
4
6
  result.push({ ...d.data(), __key: d.id });
5
7
  });
6
- return result.length > 0 ? result : null;
8
+ return result;
7
9
  };
8
10
 
9
- export const getGroupedResultFirestore = (snapshot: any) => {
10
- const groupedResult = { added: [], modified: [], removed: [] };
11
+ export const getGroupedResultFirestore = (snapshot: QuerySnapshot) => {
12
+ const groupedResult: { added: DocumentData[]; modified: DocumentData[]; removed: DocumentData[] } = {
13
+ added: [],
14
+ modified: [],
15
+ removed: [],
16
+ };
11
17
  snapshot.docChanges().forEach((change) => {
12
18
  groupedResult[change.type].push(change.doc.data());
13
19
  });
@@ -1,5 +1,6 @@
1
+ /* eslint-disable max-params */
1
2
  import { Database } from "firebase-admin/database";
2
- import { RequestInstance } from "@hyper-fetch/core";
3
+ import { getAdapterBindings } from "@hyper-fetch/core";
3
4
 
4
5
  import { RealtimeDBMethodsUnion } from "adapter/types";
5
6
  import { getStatus, isDocOrQuery } from "utils";
@@ -11,26 +12,36 @@ import {
11
12
  SharedQueryConstraints,
12
13
  } from "constraints";
13
14
 
14
- export const getRealtimeDbAdminMethods = <R extends RequestInstance>(
15
- request: R,
16
- database: Database,
17
- url: string,
15
+ export const getRealtimeDbAdminMethods = ({
16
+ database,
17
+ url,
18
18
  onSuccess,
19
19
  onError,
20
- resolve,
21
- events: { onRequestStart; onResponseEnd; onResponseStart; onRequestEnd },
22
- ): ((
20
+ onResponseStart,
21
+ onRequestStart,
22
+ onRequestEnd,
23
+ onResponseEnd,
24
+ }: {
25
+ database: Database;
26
+ url: string;
27
+ onSuccess: Awaited<ReturnType<typeof getAdapterBindings>>["onSuccess"];
28
+ onError: Awaited<ReturnType<typeof getAdapterBindings>>["onError"];
29
+ onResponseStart: Awaited<ReturnType<typeof getAdapterBindings>>["onResponseStart"];
30
+ onRequestStart: Awaited<ReturnType<typeof getAdapterBindings>>["onRequestStart"];
31
+ onRequestEnd: Awaited<ReturnType<typeof getAdapterBindings>>["onRequestEnd"];
32
+ onResponseEnd: Awaited<ReturnType<typeof getAdapterBindings>>["onResponseEnd"];
33
+ }): ((
23
34
  methodName: RealtimeDBMethodsUnion,
24
35
  data: {
25
36
  constraints: PermittedConstraints<RealtimePermittedMethods, RealtimeConstraintsUnion | SharedQueryConstraints>[];
26
- data: any;
37
+ payload: any;
27
38
  options: Record<string, any>;
28
39
  },
29
40
  ) => Promise<void>) => {
30
41
  const [fullUrl] = url.split("?");
31
42
  const path = database.ref(fullUrl);
32
43
  const methods = {
33
- get: async ({ constraints }) => {
44
+ get: async ({ constraints = [] }) => {
34
45
  const docOrQuery = isDocOrQuery(fullUrl);
35
46
  const q = applyRealtimeAdminConstraints(path, constraints);
36
47
  const snapshot = await q.get();
@@ -38,15 +49,15 @@ export const getRealtimeDbAdminMethods = <R extends RequestInstance>(
38
49
  const status = getStatus(res);
39
50
  return { result: res, status, extra: { ref: path, snapshot } };
40
51
  },
41
- set: async ({ data }) => {
52
+ set: async ({ data }: { data?: any }) => {
42
53
  await path.set(data);
43
54
  return { result: data, status: "success", extra: { ref: path } };
44
55
  },
45
- push: async ({ data }) => {
56
+ push: async ({ data }: { data?: any }) => {
46
57
  const resRef = await path.push(data);
47
58
  return { result: { ...data, __key: resRef.key }, status: "success", extra: { ref: resRef, key: resRef.key } };
48
59
  },
49
- update: async ({ data }) => {
60
+ update: async ({ data }: { data?: any }) => {
50
61
  await path.update(data);
51
62
  return { result: data, status: "success", extra: { ref: path } };
52
63
  },
@@ -58,17 +69,17 @@ export const getRealtimeDbAdminMethods = <R extends RequestInstance>(
58
69
 
59
70
  return async (methodName: RealtimeDBMethodsUnion, data) => {
60
71
  try {
61
- events.onRequestStart();
62
- const { result, status, extra } = await methods[methodName](data);
63
- events.onRequestEnd();
64
- events.onResponseStart();
65
- onSuccess(result, status, extra, resolve);
66
- events.onResponseEnd();
67
- } catch (e) {
68
- events.onRequestEnd();
69
- events.onResponseStart();
70
- onError(e, "error", {}, resolve);
71
- events.onResponseEnd();
72
+ onRequestStart();
73
+ const { result, status, extra } = await methods[methodName](data as any);
74
+ onRequestEnd();
75
+ onResponseStart();
76
+ onSuccess({ data: result, status, extra });
77
+ onResponseEnd();
78
+ } catch (error) {
79
+ onRequestEnd();
80
+ onResponseStart();
81
+ onError({ error, status: "error", extra: {} });
82
+ onResponseEnd();
72
83
  }
73
84
  };
74
85
  };
@@ -1,95 +1,81 @@
1
- import { Database } from "firebase-admin/lib/database";
2
- import { getSocketAdapterBindings } from "@hyper-fetch/sockets";
1
+ import { Database, DataSnapshot } from "firebase-admin/database";
2
+ import { SocketAdapter } from "@hyper-fetch/sockets";
3
3
 
4
4
  import { applyRealtimeAdminConstraints, getOrderedResultRealtime } from "./utils";
5
5
  import { getStatus, isDocOrQuery } from "utils";
6
6
  import { RealtimeAdminOnValueMethodExtra, RealtimeAdminSocketAdapterType } from "adapter";
7
7
 
8
- export const realtimeSocketsAdmin = (database: Database): RealtimeAdminSocketAdapterType => {
9
- return (socket) => {
10
- const {
11
- open,
12
- connecting,
13
- reconnectionAttempts,
14
- listeners,
15
- removeListener,
16
- onConnect,
17
- onReconnect,
18
- onDisconnect,
19
- onListen,
20
- onOpen,
21
- onClose,
22
- onEvent,
23
- onError,
24
- } = getSocketAdapterBindings(socket, { open: true });
8
+ export const realtimeSocketsAdmin = (database: Database) => {
9
+ return (
10
+ new SocketAdapter({
11
+ name: "firebase-admin-realtime",
12
+ defaultConnected: true,
13
+ }) as unknown as RealtimeAdminSocketAdapterType
14
+ ).setConnector(
15
+ ({ socket, onReconnect, onConnect, onConnected, onDisconnect, onDisconnected, onListen, onEvent, onError }) => {
16
+ const connect = async () => {
17
+ const enabled = onConnect();
25
18
 
26
- const connect = () => {
27
- const enabled = onConnect();
19
+ if (enabled) {
20
+ database.goOnline();
21
+ onConnected();
22
+ }
23
+ };
28
24
 
29
- if (enabled) {
30
- database.goOnline();
31
- onOpen();
32
- }
33
- };
25
+ const disconnect = async () => {
26
+ database.goOffline();
27
+ onDisconnect();
28
+ onDisconnected();
29
+ };
34
30
 
35
- const disconnect = () => {
36
- database.goOffline();
37
- onDisconnect();
38
- onClose();
39
- };
31
+ const reconnect = () => {
32
+ onReconnect({ disconnect, connect });
33
+ };
40
34
 
41
- const reconnect = () => {
42
- onReconnect(disconnect, connect);
43
- };
35
+ const listen: RealtimeAdminSocketAdapterType["listen"] = (listener, callback) => {
36
+ const fullUrl = socket.url + listener.topic;
37
+ const path = database.ref(fullUrl);
38
+ const { options } = listener;
39
+ const onlyOnce = options?.onlyOnce || false;
40
+ const q = applyRealtimeAdminConstraints(path, options?.constraints || []);
41
+ const method = onlyOnce === true ? "once" : "on";
42
+ q[method](
43
+ "value",
44
+ (snapshot) => {
45
+ const getSnapshotData = (s: DataSnapshot) => (s.val() ? { ...s.val(), __key: s.key } : null);
46
+ const response =
47
+ isDocOrQuery(fullUrl) === "doc" ? getSnapshotData(snapshot) : getOrderedResultRealtime(snapshot);
48
+ const status = getStatus(response);
49
+ const extra: RealtimeAdminOnValueMethodExtra = { ref: path, snapshot, status };
50
+ callback({ data: response, extra });
51
+ onEvent({ topic: listener.topic, data: response, extra });
52
+ },
53
+ (error) => {
54
+ onError({ error });
55
+ },
56
+ );
57
+ const unsubscribe = () => q.off("value");
58
+ const unmount = onListen({ listener, callback, onUnmount: unsubscribe });
44
59
 
45
- const listen: ReturnType<RealtimeAdminSocketAdapterType>["listen"] = (listener, callback) => {
46
- const fullUrl = socket.url + listener.endpoint;
47
- const path = database.ref(fullUrl);
48
- const { options } = listener;
49
- const onlyOnce = options?.onlyOnce || false;
50
- const q = applyRealtimeAdminConstraints(path, options?.constraints || []);
51
- const method = onlyOnce === true ? "once" : "on";
52
- q[method](
53
- "value",
54
- (snapshot) => {
55
- const getSnapshotData = (s) => (s.val() ? { ...s.val(), __key: s.key } : null);
56
- const response =
57
- isDocOrQuery(fullUrl) === "doc" ? getSnapshotData(snapshot) : getOrderedResultRealtime(snapshot);
58
- const status = getStatus(response);
59
- const extra: RealtimeAdminOnValueMethodExtra = { ref: path, snapshot, status };
60
- callback({ data: response, extra });
61
- onEvent(listener.endpoint, response, extra);
62
- },
63
- (error) => {
64
- onError(error);
65
- },
66
- );
67
- const unsubscribe = () => q.off("value");
68
- const unmount = onListen(listener, callback, unsubscribe);
60
+ const clearListeners = () => {
61
+ unsubscribe();
62
+ unmount();
63
+ };
69
64
 
70
- const clearListeners = () => {
71
- unsubscribe();
72
- unmount();
65
+ return clearListeners;
73
66
  };
74
67
 
75
- return clearListeners;
76
- };
77
-
78
- const emit = async () => {
79
- throw new Error("Cannot emit from Realtime database socket.");
80
- };
68
+ const emit = async () => {
69
+ throw new Error("Cannot emit from Realtime database socket.");
70
+ };
81
71
 
82
- return {
83
- open,
84
- reconnectionAttempts,
85
- listeners,
86
- connecting,
87
- listen,
88
- removeListener,
89
- emit,
90
- connect,
91
- reconnect,
92
- disconnect,
93
- };
94
- };
72
+ return {
73
+ connect,
74
+ reconnect,
75
+ disconnect,
76
+ listen,
77
+ emit,
78
+ };
79
+ },
80
+ );
95
81
  };
@@ -1,8 +1,8 @@
1
- import { Reference } from "firebase-admin/lib/database";
1
+ import { Query } from "firebase-admin/database";
2
2
 
3
3
  import { RealtimePermittedMethods, RealtimeQueryConstraints, SharedQueryConstraints } from "constraints";
4
4
 
5
- export const applyRealtimeAdminConstraint = (ref: Reference, { type, values }: RealtimePermittedMethods) => {
5
+ export const applyRealtimeAdminConstraint = (ref: Query, { type, values }: RealtimePermittedMethods) => {
6
6
  switch (type) {
7
7
  case RealtimeQueryConstraints.ORDER_BY_CHILD: {
8
8
  const [value] = values;
@@ -47,7 +47,7 @@ export const applyRealtimeAdminConstraint = (ref: Reference, { type, values }: R
47
47
  }
48
48
  };
49
49
 
50
- export const applyRealtimeAdminConstraints = (ref: Reference, constraints: RealtimePermittedMethods[]) => {
50
+ export const applyRealtimeAdminConstraints = (ref: Query, constraints: RealtimePermittedMethods[]) => {
51
51
  return constraints.reduce((collection, constraint) => {
52
52
  return applyRealtimeAdminConstraint(collection, constraint);
53
53
  }, ref);
@@ -1,5 +1,7 @@
1
- export const getOrderedResultRealtime = (snapshot: any) => {
2
- const res = [];
1
+ import { DataSnapshot } from "firebase-admin/database";
2
+
3
+ export const getOrderedResultRealtime = (snapshot: DataSnapshot) => {
4
+ const res: any = [];
3
5
  snapshot.forEach((child) => {
4
6
  res.push({ ...child.val(), __key: child.key });
5
7
  });
@@ -1,9 +1,15 @@
1
- import { RequestInstance } from "@hyper-fetch/core";
1
+ import { ClientInstance, RequestInstance } from "@hyper-fetch/core";
2
2
 
3
- export const setCacheManually = <R extends RequestInstance>(
4
- request: R,
3
+ import { FirestoreAdapterType } from "adapter";
4
+
5
+ export const setCacheManually = (
6
+ request: RequestInstance<{
7
+ client: ClientInstance<{
8
+ adapter: FirestoreAdapterType;
9
+ }>;
10
+ }>,
5
11
  response: { value: any; status: "success" | "error" | "emptyResource" },
6
- extra,
12
+ extra: any,
7
13
  ) => {
8
14
  if (["success", "emptyResource"].includes(response.status)) {
9
15
  request.client.cache.set(request, {
@@ -15,19 +21,25 @@ export const setCacheManually = <R extends RequestInstance>(
15
21
  isCanceled: false,
16
22
  isOffline: false,
17
23
  retries: 0,
18
- timestamp: +new Date(),
24
+ requestTimestamp: +new Date(),
25
+ responseTimestamp: +new Date(),
26
+ addedTimestamp: +new Date(),
27
+ triggerTimestamp: +new Date(),
19
28
  });
20
29
  } else {
21
30
  request.client.cache.set(request, {
22
31
  data: null,
23
- status: "error",
32
+ status: "error" as const,
24
33
  error: response.value,
25
34
  success: false,
26
35
  extra,
27
36
  isCanceled: false,
28
37
  isOffline: false,
29
38
  retries: 0,
30
- timestamp: +new Date(),
39
+ requestTimestamp: +new Date(),
40
+ responseTimestamp: +new Date(),
41
+ addedTimestamp: +new Date(),
42
+ triggerTimestamp: +new Date(),
31
43
  });
32
44
  }
33
45
  };
package/tsconfig.json CHANGED
@@ -4,5 +4,5 @@
4
4
  "rootDir": ".",
5
5
  "baseUrl": "./src"
6
6
  },
7
- "exclude": ["dist", "jest.config.ts"]
7
+ "exclude": ["node_modules", "dist", "jest.config.ts", "__tests__"]
8
8
  }