@tatsuokaniwa/swr-firestore 2.0.1 → 2.0.3

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.
package/README.md CHANGED
@@ -161,19 +161,26 @@ import type {
161
161
  startAt,
162
162
  where,
163
163
  } from "firebase/firestore";
164
+
165
+ type DocumentId = "id";
164
166
  // First argument of hook, specifies options to firestore, and is also used as a key for SWR.
165
167
  type KeyParams<T> =
166
168
  | {
167
169
  // The path to the collection or document of Firestore.
168
170
  path: string;
169
171
  // `Paths` means object's property path, including nested object
170
- where?: [Paths<T>, Parameters<typeof where>[1], ValueOf<T> | unknown][];
171
- orderBy?: [Paths<T>, Parameters<typeof orderBy>[1]][];
172
+ where?: [
173
+ Paths<T> | DocumentId,
174
+ Parameters<typeof where>[1],
175
+ ValueOf<T> | unknown
176
+ ][];
177
+ orderBy?: [Paths<T> | DocumentId, Parameters<typeof orderBy>[1]][];
172
178
  startAt?: Parameters<typeof startAt>;
173
179
  startAfter?: Parameters<typeof startAfter>;
174
180
  endAt?: Parameters<typeof endAt>;
175
181
  endBefore?: Parameters<typeof endBefore>;
176
182
  limit?: number;
183
+ limitToLast?: number;
177
184
  // Array of field names that should be parsed as dates.
178
185
  parseDates?: Paths<T>[];
179
186
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { collection, getFirestore, query, where, orderBy, startAt, startAfter, endAt, endBefore, limit, onSnapshot, getCountFromServer, collectionGroup, doc, getDocFromCache, getDoc, getDocsFromCache, getDocs } from "firebase/firestore";
1
+ import { collection, getFirestore, query, where, orderBy, startAt, startAfter, endAt, endBefore, limit, limitToLast, onSnapshot, getCountFromServer, collectionGroup, doc, getDocFromCache, getDoc, getDocsFromCache, getDocs } from "firebase/firestore";
2
2
  import { get, set } from "lodash-es";
3
3
  import useSWRSubscription from "swr/subscription";
4
4
  import useSWR from "swr";
@@ -48,8 +48,8 @@ const useCollection = (params, swrOptions) => {
48
48
  if (isQueryConstraintParams(params)) {
49
49
  q = query(ref, ...params.queryConstraints);
50
50
  } else {
51
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
52
- q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : []);
51
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
52
+ q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : [], ...ltl ? [limitToLast(ltl)] : []);
53
53
  }
54
54
  const unsub = onSnapshot(q.withConverter(converter), (qs) => {
55
55
  next(null, qs.docs.map((x) => x.data()));
@@ -70,8 +70,8 @@ const useCollectionCount = (params, swrOptions) => {
70
70
  if (isQueryConstraintParams(params)) {
71
71
  q = query(ref, ...params.queryConstraints);
72
72
  } else {
73
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
74
- q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : []);
73
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
74
+ q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : [], ...ltl ? [limitToLast(ltl)] : []);
75
75
  }
76
76
  const sn = await getCountFromServer(q);
77
77
  return sn.data().count;
@@ -93,8 +93,8 @@ const useCollectionGroup = (params, swrOptions) => {
93
93
  if (isQueryConstraintParams(params)) {
94
94
  q = query(ref, ...params.queryConstraints);
95
95
  } else {
96
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
97
- q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : []);
96
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
97
+ q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : [], ...ltl ? [limitToLast(ltl)] : []);
98
98
  }
99
99
  const unsub = onSnapshot(q.withConverter(converter), (qs) => {
100
100
  next(null, qs.docs.map((x) => x.data()));
@@ -115,8 +115,8 @@ const useCollectionGroupCount = (params, swrOptions) => {
115
115
  if (isQueryConstraintParams(params)) {
116
116
  q = query(ref, ...params.queryConstraints);
117
117
  } else {
118
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
119
- q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : []);
118
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
119
+ q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : [], ...ltl ? [limitToLast(ltl)] : []);
120
120
  }
121
121
  const sn = await getCountFromServer(q);
122
122
  return sn.data().count;
@@ -183,8 +183,8 @@ const useGetDocs = (params, swrOptions) => {
183
183
  if (isQueryConstraintParams(params)) {
184
184
  q = query(ref, ...params.queryConstraints);
185
185
  } else {
186
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
187
- q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : []);
186
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
187
+ q = query(ref, ...(w ? w : []).map((q2) => where(...q2)), ...(o ? o : []).map((q2) => orderBy(...q2)), ...s ? [startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [limit(l)] : [], ...ltl ? [limitToLast(ltl)] : []);
188
188
  }
189
189
  const getFn = params.useOfflineCache ? getDocsFromCache : getDocs;
190
190
  const sn = await getFn(q.withConverter(converter));
@@ -50,8 +50,8 @@ const useCollection = (params, swrOptions) => {
50
50
  if (isQueryConstraintParams(params)) {
51
51
  q = firestore.query(ref, ...params.queryConstraints);
52
52
  } else {
53
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
54
- q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : []);
53
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
54
+ q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : [], ...ltl ? [firestore.limitToLast(ltl)] : []);
55
55
  }
56
56
  const unsub = firestore.onSnapshot(q.withConverter(converter), (qs) => {
57
57
  next(null, qs.docs.map((x) => x.data()));
@@ -72,8 +72,8 @@ const useCollectionCount = (params, swrOptions) => {
72
72
  if (isQueryConstraintParams(params)) {
73
73
  q = firestore.query(ref, ...params.queryConstraints);
74
74
  } else {
75
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
76
- q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : []);
75
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
76
+ q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : [], ...ltl ? [firestore.limitToLast(ltl)] : []);
77
77
  }
78
78
  const sn = await firestore.getCountFromServer(q);
79
79
  return sn.data().count;
@@ -95,8 +95,8 @@ const useCollectionGroup = (params, swrOptions) => {
95
95
  if (isQueryConstraintParams(params)) {
96
96
  q = firestore.query(ref, ...params.queryConstraints);
97
97
  } else {
98
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
99
- q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : []);
98
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
99
+ q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : [], ...ltl ? [firestore.limitToLast(ltl)] : []);
100
100
  }
101
101
  const unsub = firestore.onSnapshot(q.withConverter(converter), (qs) => {
102
102
  next(null, qs.docs.map((x) => x.data()));
@@ -117,8 +117,8 @@ const useCollectionGroupCount = (params, swrOptions) => {
117
117
  if (isQueryConstraintParams(params)) {
118
118
  q = firestore.query(ref, ...params.queryConstraints);
119
119
  } else {
120
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
121
- q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : []);
120
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
121
+ q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : [], ...ltl ? [firestore.limitToLast(ltl)] : []);
122
122
  }
123
123
  const sn = await firestore.getCountFromServer(q);
124
124
  return sn.data().count;
@@ -185,8 +185,8 @@ const useGetDocs = (params, swrOptions) => {
185
185
  if (isQueryConstraintParams(params)) {
186
186
  q = firestore.query(ref, ...params.queryConstraints);
187
187
  } else {
188
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
189
- q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : []);
188
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
189
+ q = firestore.query(ref, ...(w ? w : []).map((q2) => firestore.where(...q2)), ...(o ? o : []).map((q2) => firestore.orderBy(...q2)), ...s ? [firestore.startAt(...Array.isArray(s) ? s : [s])] : [], ...sa ? [firestore.startAfter(...Array.isArray(sa) ? sa : [sa])] : [], ...e ? [firestore.endAt(...Array.isArray(e) ? e : [e])] : [], ...eb ? [firestore.endBefore(...Array.isArray(eb) ? eb : [eb])] : [], ...l ? [firestore.limit(l)] : [], ...ltl ? [firestore.limitToLast(ltl)] : []);
190
190
  }
191
191
  const getFn = params.useOfflineCache ? firestore.getDocsFromCache : firestore.getDocs;
192
192
  const sn = await getFn(q.withConverter(converter));
@@ -35,7 +35,7 @@ const getCollection = async (params) => {
35
35
  const converter = getFirestoreConverter(parseDates);
36
36
  const collectionRef = db.collection(path).withConverter(converter);
37
37
  let queryRef = null;
38
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
38
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
39
39
  if (w) {
40
40
  w.forEach((q) => {
41
41
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -61,6 +61,9 @@ const getCollection = async (params) => {
61
61
  if (l) {
62
62
  queryRef = (queryRef ?? collectionRef).limit(l);
63
63
  }
64
+ if (ltl) {
65
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
66
+ }
64
67
  const sn = await (queryRef ?? collectionRef).get();
65
68
  return {
66
69
  key: createSwrKey(params),
@@ -72,7 +75,7 @@ const getCollectionCount = async (params) => {
72
75
  const db = getFirestore();
73
76
  const collectionRef = db.collection(path);
74
77
  let queryRef = null;
75
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
78
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
76
79
  if (w) {
77
80
  w.forEach((q) => {
78
81
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -98,6 +101,9 @@ const getCollectionCount = async (params) => {
98
101
  if (l) {
99
102
  queryRef = (queryRef ?? collectionRef).limit(l);
100
103
  }
104
+ if (ltl) {
105
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
106
+ }
101
107
  const sn = await (queryRef ?? collectionRef).count().get();
102
108
  return {
103
109
  key: createSwrKey({ ...params, count: true }),
@@ -110,7 +116,7 @@ const getCollectionGroup = async (params) => {
110
116
  const converter = getFirestoreConverter(parseDates);
111
117
  const collectionRef = db.collectionGroup(path).withConverter(converter);
112
118
  let queryRef = null;
113
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
119
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
114
120
  if (w) {
115
121
  w.forEach((q) => {
116
122
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -136,6 +142,9 @@ const getCollectionGroup = async (params) => {
136
142
  if (l) {
137
143
  queryRef = (queryRef ?? collectionRef).limit(l);
138
144
  }
145
+ if (ltl) {
146
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
147
+ }
139
148
  const sn = await (queryRef ?? collectionRef).get();
140
149
  return {
141
150
  key: createSwrKey(params),
@@ -147,7 +156,7 @@ const getCollectionGroupCount = async (params) => {
147
156
  const db = getFirestore();
148
157
  const collectionRef = db.collectionGroup(path);
149
158
  let queryRef = null;
150
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
159
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
151
160
  if (w) {
152
161
  w.forEach((q) => {
153
162
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -173,6 +182,9 @@ const getCollectionGroupCount = async (params) => {
173
182
  if (l) {
174
183
  queryRef = (queryRef ?? collectionRef).limit(l);
175
184
  }
185
+ if (ltl) {
186
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
187
+ }
176
188
  const sn = await (queryRef ?? collectionRef).count().get();
177
189
  return {
178
190
  key: createSwrKey({ ...params, count: true }),
@@ -37,7 +37,7 @@ const getCollection = async (params) => {
37
37
  const converter = getFirestoreConverter(parseDates);
38
38
  const collectionRef = db.collection(path).withConverter(converter);
39
39
  let queryRef = null;
40
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
40
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
41
41
  if (w) {
42
42
  w.forEach((q) => {
43
43
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -63,6 +63,9 @@ const getCollection = async (params) => {
63
63
  if (l) {
64
64
  queryRef = (queryRef ?? collectionRef).limit(l);
65
65
  }
66
+ if (ltl) {
67
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
68
+ }
66
69
  const sn = await (queryRef ?? collectionRef).get();
67
70
  return {
68
71
  key: createSwrKey(params),
@@ -74,7 +77,7 @@ const getCollectionCount = async (params) => {
74
77
  const db = firestore.getFirestore();
75
78
  const collectionRef = db.collection(path);
76
79
  let queryRef = null;
77
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
80
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
78
81
  if (w) {
79
82
  w.forEach((q) => {
80
83
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -100,6 +103,9 @@ const getCollectionCount = async (params) => {
100
103
  if (l) {
101
104
  queryRef = (queryRef ?? collectionRef).limit(l);
102
105
  }
106
+ if (ltl) {
107
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
108
+ }
103
109
  const sn = await (queryRef ?? collectionRef).count().get();
104
110
  return {
105
111
  key: createSwrKey({ ...params, count: true }),
@@ -112,7 +118,7 @@ const getCollectionGroup = async (params) => {
112
118
  const converter = getFirestoreConverter(parseDates);
113
119
  const collectionRef = db.collectionGroup(path).withConverter(converter);
114
120
  let queryRef = null;
115
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
121
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
116
122
  if (w) {
117
123
  w.forEach((q) => {
118
124
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -138,6 +144,9 @@ const getCollectionGroup = async (params) => {
138
144
  if (l) {
139
145
  queryRef = (queryRef ?? collectionRef).limit(l);
140
146
  }
147
+ if (ltl) {
148
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
149
+ }
141
150
  const sn = await (queryRef ?? collectionRef).get();
142
151
  return {
143
152
  key: createSwrKey(params),
@@ -149,7 +158,7 @@ const getCollectionGroupCount = async (params) => {
149
158
  const db = firestore.getFirestore();
150
159
  const collectionRef = db.collectionGroup(path);
151
160
  let queryRef = null;
152
- const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l } = params;
161
+ const { where: w, orderBy: o, startAt: s, startAfter: sa, endAt: e, endBefore: eb, limit: l, limitToLast: ltl } = params;
153
162
  if (w) {
154
163
  w.forEach((q) => {
155
164
  queryRef = (queryRef ?? collectionRef).where(...q);
@@ -175,6 +184,9 @@ const getCollectionGroupCount = async (params) => {
175
184
  if (l) {
176
185
  queryRef = (queryRef ?? collectionRef).limit(l);
177
186
  }
187
+ if (ltl) {
188
+ queryRef = (queryRef ?? collectionRef).limitToLast(ltl);
189
+ }
178
190
  const sn = await (queryRef ?? collectionRef).count().get();
179
191
  return {
180
192
  key: createSwrKey({ ...params, count: true }),
@@ -1,13 +1,15 @@
1
1
  import type { OrderByDirection, Query, QueryDocumentSnapshot, WhereFilterOp } from "firebase-admin/firestore";
2
2
  import type { Paths, ValueOf } from "../../util/type.js";
3
+ export type DocumentId = "id";
3
4
  export type QueryParams<T> = {
4
- where?: [Paths<T>, WhereFilterOp, ValueOf<T> | unknown][];
5
- orderBy?: [Paths<T>, OrderByDirection][];
5
+ where?: [Paths<T> | DocumentId, WhereFilterOp, ValueOf<T> | unknown][];
6
+ orderBy?: [Paths<T> | DocumentId, OrderByDirection][];
6
7
  startAt?: Parameters<Query["startAt"]>;
7
8
  startAfter?: Parameters<Query["startAfter"]>;
8
9
  endAt?: Parameters<Query["endAt"]>;
9
10
  endBefore?: Parameters<Query["endBefore"]>;
10
11
  limit?: number;
12
+ limitToLast?: number;
11
13
  };
12
14
  type BaseParams<T> = {
13
15
  path: string;
@@ -26,18 +26,24 @@ type Prev = [
26
26
  20,
27
27
  ...0[]
28
28
  ];
29
+ export type DocumentId = "id";
29
30
  export type Paths<T, D extends number = 3> = [D] extends [never] ? never : T extends object ? {
30
31
  [K in keyof T]-?: K extends string | number ? `${K}` | Join<K, Paths<T[K], Prev[D]>> : never;
31
32
  }[keyof T] : "";
32
33
  export type ValueOf<T> = T[keyof T];
33
34
  export type QueryParams<T> = {
34
- where?: [Paths<T>, Parameters<typeof where>[1], ValueOf<T> | unknown][];
35
- orderBy?: [Paths<T>, Parameters<typeof orderBy>[1]][];
35
+ where?: [
36
+ Paths<T> | DocumentId,
37
+ Parameters<typeof where>[1],
38
+ ValueOf<T> | unknown
39
+ ][];
40
+ orderBy?: [Paths<T> | DocumentId, Parameters<typeof orderBy>[1]][];
36
41
  startAt?: Parameters<typeof startAt>;
37
42
  startAfter?: Parameters<typeof startAfter>;
38
43
  endAt?: Parameters<typeof endAt>;
39
44
  endBefore?: Parameters<typeof endBefore>;
40
45
  limit?: number;
46
+ limitToLast?: number;
41
47
  };
42
48
  export type QueryConstraintParams = {
43
49
  queryConstraints?: [QueryCompositeFilterConstraint, ...Array<QueryNonFilterConstraint>] | QueryConstraint[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tatsuokaniwa/swr-firestore",
3
3
  "description": "React Hooks library for Firestore using SWR's subscription feature.",
4
- "version": "2.0.1",
4
+ "version": "2.0.3",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/t-k/swr-firestore.git"
@@ -65,21 +65,21 @@
65
65
  "@types/react": "^18.0.28",
66
66
  "@types/react-dom": "^18.0.11",
67
67
  "@typescript-eslint/eslint-plugin": "^5.56.0",
68
- "@vitejs/plugin-react": "^3.1.0",
69
- "@vitest/coverage-c8": "^0.29.3",
68
+ "@vitejs/plugin-react": "^4.0.0",
69
+ "@vitest/coverage-c8": "^0.32.0",
70
70
  "c8": "^7.13.0",
71
71
  "eslint": "^8.36.0",
72
72
  "eslint-plugin-react": "^7.32.2",
73
73
  "firebase": "^9.11.0 < 10.0.0",
74
74
  "firebase-admin": "^11.0.0 <12.0.0",
75
- "jsdom": "^21.1.1",
75
+ "jsdom": "^22.0.0",
76
76
  "prettier": "^2.8.5",
77
77
  "react": "^18.2.0",
78
78
  "rollup-plugin-typescript-paths": "^1.4.0",
79
79
  "swr": "^2.1.0 <3.0.0",
80
80
  "typescript": "^5.0.2",
81
81
  "vite-tsconfig-paths": "^4.0.7",
82
- "vitest": "^0.30.0"
82
+ "vitest": "^0.32.0"
83
83
  },
84
84
  "peerDependencies": {
85
85
  "firebase": "^9.11.0 < 10.0.0",