@cravery/firebase 0.0.31 → 0.0.32

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 +1 @@
1
- {"version":3,"file":"equipment.d.ts","sourceRoot":"","sources":["../../src/repository/equipment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,eAAe,CAAC;AAKvB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErD,qBAAa,mBAAoB,SAAQ,cAAc,CACrD,eAAe,EACf,mBAAmB,EACnB,sBAAsB,CACvB;IACC,SAAS,CAAC,QAAQ,CAAC,cAAc,SAAyB;IAC1D,SAAS,CAAC,QAAQ,CAAC,UAAU,eAAe;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,gGAA0B;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,mGAA6B;gBAEpD,EAAE,EAAE,SAAS;IAIzB,SAAS,CAAC,KAAK,CACb,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,sBAAsB,GAC9B,eAAe;IAIlB,SAAS,CAAC,KAAK,CACb,SAAS,EAAE,eAAe,GACzB,WAAW,CAAC,mBAAmB,EAAE,sBAAsB,CAAC;IA4BrD,aAAa,CACjB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,mBAA+B,GACzC,OAAO,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;CAanD"}
1
+ {"version":3,"file":"equipment.d.ts","sourceRoot":"","sources":["../../src/repository/equipment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAa,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,eAAe,CAAC;AAKvB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGrD,qBAAa,mBAAoB,SAAQ,cAAc,CACrD,eAAe,EACf,mBAAmB,EACnB,sBAAsB,CACvB;IACC,SAAS,CAAC,QAAQ,CAAC,cAAc,SAAyB;IAC1D,SAAS,CAAC,QAAQ,CAAC,UAAU,eAAe;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,gGAA0B;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,mGAA6B;gBAEpD,EAAE,EAAE,SAAS;IAIzB,SAAS,CAAC,KAAK,CACb,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,sBAAsB,GAC9B,eAAe;IAIlB,SAAS,CAAC,KAAK,CACb,SAAS,EAAE,eAAe,GACzB,WAAW,CAAC,mBAAmB,EAAE,sBAAsB,CAAC;IA4BrD,aAAa,CACjB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,mBAA+B,GACzC,OAAO,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;CAkDnD"}
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EquipmentRepository = void 0;
4
+ const firestore_1 = require("firebase-admin/firestore");
4
5
  const core_1 = require("@cravery/core");
5
6
  const converter_1 = require("../converter");
6
7
  const base_1 = require("./base");
8
+ const cursor_1 = require("../utils/cursor");
7
9
  class EquipmentRepository extends base_1.BaseRepository {
8
10
  constructor(db) {
9
11
  super(db);
@@ -32,10 +34,46 @@ class EquipmentRepository extends base_1.BaseRepository {
32
34
  };
33
35
  }
34
36
  async getByCategory(category, locale, limit = 20, cursor, direction = "forward") {
35
- const baseQuery = this.metaCollection
37
+ const isForward = direction === "forward";
38
+ const sortDir = isForward ? "desc" : "asc";
39
+ // Firestore requires orderBy on inequality field (status) first
40
+ let query = this.metaCollection
36
41
  .where("category", "==", category)
37
- .where("status", "!=", "deleted");
38
- return this.executePaginatedQuery(baseQuery, locale, limit, cursor, direction);
42
+ .where("status", "!=", "deleted")
43
+ .orderBy("status", sortDir)
44
+ .orderBy("createdAt", sortDir)
45
+ .orderBy(firestore_1.FieldPath.documentId(), sortDir);
46
+ if (cursor) {
47
+ const [timestamp, id] = (0, cursor_1.cursorToFirestoreValues)(cursor);
48
+ query = query.startAfter(timestamp, id);
49
+ }
50
+ const snapshot = await query.limit(limit + 1).get();
51
+ const hasMore = snapshot.docs.length > limit;
52
+ let docs = hasMore ? snapshot.docs.slice(0, -1) : snapshot.docs;
53
+ if (!isForward) {
54
+ docs = docs.reverse();
55
+ }
56
+ if (docs.length === 0) {
57
+ return {
58
+ data: [],
59
+ startCursor: null,
60
+ endCursor: null,
61
+ hasNextPage: false,
62
+ hasPreviousPage: false,
63
+ };
64
+ }
65
+ const entities = await this.hydrate(docs, locale);
66
+ const firstDoc = docs[0];
67
+ const lastDoc = docs[docs.length - 1];
68
+ const firstCreatedAt = firstDoc.get("createdAt");
69
+ const lastCreatedAt = lastDoc.get("createdAt");
70
+ return {
71
+ data: entities,
72
+ startCursor: (0, cursor_1.encodeCursor)(firstCreatedAt, firstDoc.id),
73
+ endCursor: (0, cursor_1.encodeCursor)(lastCreatedAt, lastDoc.id),
74
+ hasNextPage: isForward ? hasMore : !!cursor,
75
+ hasPreviousPage: isForward ? !!cursor : hasMore,
76
+ };
39
77
  }
40
78
  }
41
79
  exports.EquipmentRepository = EquipmentRepository;
@@ -1 +1 @@
1
- {"version":3,"file":"equipment.js","sourceRoot":"","sources":["../../src/repository/equipment.ts"],"names":[],"mappings":";;;AACA,wCASuB;AACvB,4CAGsB;AACtB,iCAAqD;AAErD,MAAa,mBAAoB,SAAQ,qBAIxC;IAMC,YAAY,EAAa;QACvB,KAAK,CAAC,EAAE,CAAC,CAAC;QANO,mBAAc,GAAG,kBAAW,CAAC,SAAS,CAAC;QACvC,eAAU,GAAG,WAAW,CAAC;QACzB,kBAAa,GAAG,kCAAsB,CAAC;QACvC,qBAAgB,GAAG,qCAAyB,CAAC;IAIhE,CAAC;IAES,KAAK,CACb,IAAyB,EACzB,OAA+B;QAE/B,uCAAY,IAAI,GAAK,OAAO,EAAG;IACjC,CAAC;IAES,KAAK,CACb,SAA0B;QAE1B,MAAM,EACJ,EAAE,EAAE,GAAG,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,GACL,GAAG,SAAS,CAAC;QACd,OAAO;YACL,IAAI,EAAE;gBACJ,QAAQ;gBACR,QAAQ;gBACR,IAAI;gBACJ,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,SAAS;gBACT,SAAS;aACV;YACD,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;SACxB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,QAA2B,EAC3B,MAAc,EACd,KAAK,GAAG,EAAE,EACV,MAAe,EACf,YAAiC,SAAS;QAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc;aAClC,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC;aACjC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAEpC,OAAO,IAAI,CAAC,qBAAqB,CAC/B,SAAS,EACT,MAAM,EACN,KAAK,EACL,MAAM,EACN,SAAS,CACV,CAAC;IACJ,CAAC;CACF;AAtED,kDAsEC"}
1
+ {"version":3,"file":"equipment.js","sourceRoot":"","sources":["../../src/repository/equipment.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ingredient.d.ts","sourceRoot":"","sources":["../../src/repository/ingredient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,eAAe,CAAC;AAKvB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErD,qBAAa,oBAAqB,SAAQ,cAAc,CACtD,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,CACxB;IACC,SAAS,CAAC,QAAQ,CAAC,cAAc,SAA2B;IAC5D,SAAS,CAAC,QAAQ,CAAC,UAAU,gBAAgB;IAC7C,SAAS,CAAC,QAAQ,CAAC,aAAa,iGAA2B;IAC3D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,oGAA8B;gBAErD,EAAE,EAAE,SAAS;IAIzB,SAAS,CAAC,KAAK,CACb,IAAI,EAAE,oBAAoB,EAC1B,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB;IAInB,SAAS,CAAC,KAAK,CACb,UAAU,EAAE,gBAAgB,GAC3B,WAAW,CAAC,oBAAoB,EAAE,uBAAuB,CAAC;IAgCvD,aAAa,CACjB,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,mBAA+B,GACzC,OAAO,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;IAc7C,UAAU,CACd,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,mBAA+B,GACzC,OAAO,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;CAapD"}
1
+ {"version":3,"file":"ingredient.d.ts","sourceRoot":"","sources":["../../src/repository/ingredient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAa,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,eAAe,CAAC;AAKvB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGrD,qBAAa,oBAAqB,SAAQ,cAAc,CACtD,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,CACxB;IACC,SAAS,CAAC,QAAQ,CAAC,cAAc,SAA2B;IAC5D,SAAS,CAAC,QAAQ,CAAC,UAAU,gBAAgB;IAC7C,SAAS,CAAC,QAAQ,CAAC,aAAa,iGAA2B;IAC3D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,oGAA8B;gBAErD,EAAE,EAAE,SAAS;IAIzB,SAAS,CAAC,KAAK,CACb,IAAI,EAAE,oBAAoB,EAC1B,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB;IAInB,SAAS,CAAC,KAAK,CACb,UAAU,EAAE,gBAAgB,GAC3B,WAAW,CAAC,oBAAoB,EAAE,uBAAuB,CAAC;IAgCvD,aAAa,CACjB,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,mBAA+B,GACzC,OAAO,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;IAmD7C,UAAU,CACd,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,mBAA+B,GACzC,OAAO,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;CAkDpD"}
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.IngredientRepository = void 0;
4
+ const firestore_1 = require("firebase-admin/firestore");
4
5
  const core_1 = require("@cravery/core");
5
6
  const converter_1 = require("../converter");
6
7
  const base_1 = require("./base");
8
+ const cursor_1 = require("../utils/cursor");
7
9
  class IngredientRepository extends base_1.BaseRepository {
8
10
  constructor(db) {
9
11
  super(db);
@@ -34,16 +36,88 @@ class IngredientRepository extends base_1.BaseRepository {
34
36
  };
35
37
  }
36
38
  async getByCategory(category, locale, limit = 20, cursor, direction = "forward") {
37
- const baseQuery = this.metaCollection
39
+ const isForward = direction === "forward";
40
+ const sortDir = isForward ? "desc" : "asc";
41
+ // Firestore requires orderBy on inequality field (status) first
42
+ let query = this.metaCollection
38
43
  .where("category", "==", category)
39
- .where("status", "!=", "deleted");
40
- return this.executePaginatedQuery(baseQuery, locale, limit, cursor, direction);
44
+ .where("status", "!=", "deleted")
45
+ .orderBy("status", sortDir)
46
+ .orderBy("createdAt", sortDir)
47
+ .orderBy(firestore_1.FieldPath.documentId(), sortDir);
48
+ if (cursor) {
49
+ const [timestamp, id] = (0, cursor_1.cursorToFirestoreValues)(cursor);
50
+ query = query.startAfter(timestamp, id);
51
+ }
52
+ const snapshot = await query.limit(limit + 1).get();
53
+ const hasMore = snapshot.docs.length > limit;
54
+ let docs = hasMore ? snapshot.docs.slice(0, -1) : snapshot.docs;
55
+ if (!isForward) {
56
+ docs = docs.reverse();
57
+ }
58
+ if (docs.length === 0) {
59
+ return {
60
+ data: [],
61
+ startCursor: null,
62
+ endCursor: null,
63
+ hasNextPage: false,
64
+ hasPreviousPage: false,
65
+ };
66
+ }
67
+ const entities = await this.hydrate(docs, locale);
68
+ const firstDoc = docs[0];
69
+ const lastDoc = docs[docs.length - 1];
70
+ const firstCreatedAt = firstDoc.get("createdAt");
71
+ const lastCreatedAt = lastDoc.get("createdAt");
72
+ return {
73
+ data: entities,
74
+ startCursor: (0, cursor_1.encodeCursor)(firstCreatedAt, firstDoc.id),
75
+ endCursor: (0, cursor_1.encodeCursor)(lastCreatedAt, lastDoc.id),
76
+ hasNextPage: isForward ? hasMore : !!cursor,
77
+ hasPreviousPage: isForward ? !!cursor : hasMore,
78
+ };
41
79
  }
42
80
  async getByGroup(group, locale, limit = 20, cursor, direction = "forward") {
43
- const baseQuery = this.metaCollection
81
+ const isForward = direction === "forward";
82
+ const sortDir = isForward ? "desc" : "asc";
83
+ // Firestore requires orderBy on inequality field (status) first
84
+ let query = this.metaCollection
44
85
  .where("group", "==", group)
45
- .where("status", "!=", "deleted");
46
- return this.executePaginatedQuery(baseQuery, locale, limit, cursor, direction);
86
+ .where("status", "!=", "deleted")
87
+ .orderBy("status", sortDir)
88
+ .orderBy("createdAt", sortDir)
89
+ .orderBy(firestore_1.FieldPath.documentId(), sortDir);
90
+ if (cursor) {
91
+ const [timestamp, id] = (0, cursor_1.cursorToFirestoreValues)(cursor);
92
+ query = query.startAfter(timestamp, id);
93
+ }
94
+ const snapshot = await query.limit(limit + 1).get();
95
+ const hasMore = snapshot.docs.length > limit;
96
+ let docs = hasMore ? snapshot.docs.slice(0, -1) : snapshot.docs;
97
+ if (!isForward) {
98
+ docs = docs.reverse();
99
+ }
100
+ if (docs.length === 0) {
101
+ return {
102
+ data: [],
103
+ startCursor: null,
104
+ endCursor: null,
105
+ hasNextPage: false,
106
+ hasPreviousPage: false,
107
+ };
108
+ }
109
+ const entities = await this.hydrate(docs, locale);
110
+ const firstDoc = docs[0];
111
+ const lastDoc = docs[docs.length - 1];
112
+ const firstCreatedAt = firstDoc.get("createdAt");
113
+ const lastCreatedAt = lastDoc.get("createdAt");
114
+ return {
115
+ data: entities,
116
+ startCursor: (0, cursor_1.encodeCursor)(firstCreatedAt, firstDoc.id),
117
+ endCursor: (0, cursor_1.encodeCursor)(lastCreatedAt, lastDoc.id),
118
+ hasNextPage: isForward ? hasMore : !!cursor,
119
+ hasPreviousPage: isForward ? !!cursor : hasMore,
120
+ };
47
121
  }
48
122
  }
49
123
  exports.IngredientRepository = IngredientRepository;
@@ -1 +1 @@
1
- {"version":3,"file":"ingredient.js","sourceRoot":"","sources":["../../src/repository/ingredient.ts"],"names":[],"mappings":";;;AACA,wCAUuB;AACvB,4CAGsB;AACtB,iCAAqD;AAErD,MAAa,oBAAqB,SAAQ,qBAIzC;IAMC,YAAY,EAAa;QACvB,KAAK,CAAC,EAAE,CAAC,CAAC;QANO,mBAAc,GAAG,kBAAW,CAAC,WAAW,CAAC;QACzC,eAAU,GAAG,YAAY,CAAC;QAC1B,kBAAa,GAAG,mCAAuB,CAAC;QACxC,qBAAgB,GAAG,sCAA0B,CAAC;IAIjE,CAAC;IAES,KAAK,CACb,IAA0B,EAC1B,OAAgC;QAEhC,uCAAY,IAAI,GAAK,OAAO,EAAG;IACjC,CAAC;IAES,KAAK,CACb,UAA4B;QAE5B,MAAM,EACJ,EAAE,EAAE,GAAG,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,IAAI,GACL,GAAG,UAAU,CAAC;QACf,OAAO;YACL,IAAI,EAAE;gBACJ,QAAQ;gBACR,KAAK;gBACL,QAAQ;gBACR,KAAK;gBACL,IAAI;gBACJ,YAAY;gBACZ,MAAM;gBACN,SAAS;gBACT,SAAS;gBACT,SAAS;aACV;YACD,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;SACxB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,QAA4B,EAC5B,MAAc,EACd,KAAK,GAAG,EAAE,EACV,MAAe,EACf,YAAiC,SAAS;QAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc;aAClC,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC;aACjC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAEpC,OAAO,IAAI,CAAC,qBAAqB,CAC/B,SAAS,EACT,MAAM,EACN,KAAK,EACL,MAAM,EACN,SAAS,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CACd,KAAsB,EACtB,MAAc,EACd,KAAK,GAAG,EAAE,EACV,MAAe,EACf,YAAiC,SAAS;QAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc;aAClC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC;aAC3B,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAEpC,OAAO,IAAI,CAAC,qBAAqB,CAC/B,SAAS,EACT,MAAM,EACN,KAAK,EACL,MAAM,EACN,SAAS,CACV,CAAC;IACJ,CAAC;CACF;AA9FD,oDA8FC"}
1
+ {"version":3,"file":"ingredient.js","sourceRoot":"","sources":["../../src/repository/ingredient.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cravery/firebase",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "description": "Shared Firebase Admin SDK utilities for Cravery",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,4 +1,4 @@
1
- import { Firestore } from "firebase-admin/firestore";
1
+ import { FieldPath, Firestore, Timestamp } from "firebase-admin/firestore";
2
2
  import {
3
3
  type EquipmentEntity,
4
4
  type EquipmentEntityMeta,
@@ -14,6 +14,7 @@ import {
14
14
  equipmentContentConverter,
15
15
  } from "../converter";
16
16
  import { BaseRepository, SplitResult } from "./base";
17
+ import { encodeCursor, cursorToFirestoreValues } from "../utils/cursor";
17
18
 
18
19
  export class EquipmentRepository extends BaseRepository<
19
20
  EquipmentEntity,
@@ -73,16 +74,53 @@ export class EquipmentRepository extends BaseRepository<
73
74
  cursor?: string,
74
75
  direction: PaginationDirection = "forward",
75
76
  ): Promise<CursorPaginatedResult<EquipmentEntity>> {
76
- const baseQuery = this.metaCollection
77
+ const isForward = direction === "forward";
78
+ const sortDir = isForward ? "desc" : "asc";
79
+
80
+ // Firestore requires orderBy on inequality field (status) first
81
+ let query = this.metaCollection
77
82
  .where("category", "==", category)
78
- .where("status", "!=", "deleted");
83
+ .where("status", "!=", "deleted")
84
+ .orderBy("status", sortDir)
85
+ .orderBy("createdAt", sortDir)
86
+ .orderBy(FieldPath.documentId(), sortDir);
87
+
88
+ if (cursor) {
89
+ const [timestamp, id] = cursorToFirestoreValues(cursor);
90
+ query = query.startAfter(timestamp, id);
91
+ }
92
+
93
+ const snapshot = await query.limit(limit + 1).get();
94
+ const hasMore = snapshot.docs.length > limit;
95
+ let docs = hasMore ? snapshot.docs.slice(0, -1) : snapshot.docs;
96
+
97
+ if (!isForward) {
98
+ docs = docs.reverse();
99
+ }
100
+
101
+ if (docs.length === 0) {
102
+ return {
103
+ data: [],
104
+ startCursor: null,
105
+ endCursor: null,
106
+ hasNextPage: false,
107
+ hasPreviousPage: false,
108
+ };
109
+ }
79
110
 
80
- return this.executePaginatedQuery(
81
- baseQuery,
82
- locale,
83
- limit,
84
- cursor,
85
- direction,
86
- );
111
+ const entities = await this.hydrate(docs, locale);
112
+
113
+ const firstDoc = docs[0];
114
+ const lastDoc = docs[docs.length - 1];
115
+ const firstCreatedAt = firstDoc.get("createdAt") as Timestamp;
116
+ const lastCreatedAt = lastDoc.get("createdAt") as Timestamp;
117
+
118
+ return {
119
+ data: entities,
120
+ startCursor: encodeCursor(firstCreatedAt, firstDoc.id),
121
+ endCursor: encodeCursor(lastCreatedAt, lastDoc.id),
122
+ hasNextPage: isForward ? hasMore : !!cursor,
123
+ hasPreviousPage: isForward ? !!cursor : hasMore,
124
+ };
87
125
  }
88
126
  }
@@ -1,4 +1,4 @@
1
- import { Firestore } from "firebase-admin/firestore";
1
+ import { FieldPath, Firestore, Timestamp } from "firebase-admin/firestore";
2
2
  import {
3
3
  type IngredientEntity,
4
4
  type IngredientEntityMeta,
@@ -15,6 +15,7 @@ import {
15
15
  ingredientContentConverter,
16
16
  } from "../converter";
17
17
  import { BaseRepository, SplitResult } from "./base";
18
+ import { encodeCursor, cursorToFirestoreValues } from "../utils/cursor";
18
19
 
19
20
  export class IngredientRepository extends BaseRepository<
20
21
  IngredientEntity,
@@ -78,17 +79,54 @@ export class IngredientRepository extends BaseRepository<
78
79
  cursor?: string,
79
80
  direction: PaginationDirection = "forward",
80
81
  ): Promise<CursorPaginatedResult<IngredientEntity>> {
81
- const baseQuery = this.metaCollection
82
+ const isForward = direction === "forward";
83
+ const sortDir = isForward ? "desc" : "asc";
84
+
85
+ // Firestore requires orderBy on inequality field (status) first
86
+ let query = this.metaCollection
82
87
  .where("category", "==", category)
83
- .where("status", "!=", "deleted");
84
-
85
- return this.executePaginatedQuery(
86
- baseQuery,
87
- locale,
88
- limit,
89
- cursor,
90
- direction,
91
- );
88
+ .where("status", "!=", "deleted")
89
+ .orderBy("status", sortDir)
90
+ .orderBy("createdAt", sortDir)
91
+ .orderBy(FieldPath.documentId(), sortDir);
92
+
93
+ if (cursor) {
94
+ const [timestamp, id] = cursorToFirestoreValues(cursor);
95
+ query = query.startAfter(timestamp, id);
96
+ }
97
+
98
+ const snapshot = await query.limit(limit + 1).get();
99
+ const hasMore = snapshot.docs.length > limit;
100
+ let docs = hasMore ? snapshot.docs.slice(0, -1) : snapshot.docs;
101
+
102
+ if (!isForward) {
103
+ docs = docs.reverse();
104
+ }
105
+
106
+ if (docs.length === 0) {
107
+ return {
108
+ data: [],
109
+ startCursor: null,
110
+ endCursor: null,
111
+ hasNextPage: false,
112
+ hasPreviousPage: false,
113
+ };
114
+ }
115
+
116
+ const entities = await this.hydrate(docs, locale);
117
+
118
+ const firstDoc = docs[0];
119
+ const lastDoc = docs[docs.length - 1];
120
+ const firstCreatedAt = firstDoc.get("createdAt") as Timestamp;
121
+ const lastCreatedAt = lastDoc.get("createdAt") as Timestamp;
122
+
123
+ return {
124
+ data: entities,
125
+ startCursor: encodeCursor(firstCreatedAt, firstDoc.id),
126
+ endCursor: encodeCursor(lastCreatedAt, lastDoc.id),
127
+ hasNextPage: isForward ? hasMore : !!cursor,
128
+ hasPreviousPage: isForward ? !!cursor : hasMore,
129
+ };
92
130
  }
93
131
 
94
132
  async getByGroup(
@@ -98,16 +136,53 @@ export class IngredientRepository extends BaseRepository<
98
136
  cursor?: string,
99
137
  direction: PaginationDirection = "forward",
100
138
  ): Promise<CursorPaginatedResult<IngredientEntity>> {
101
- const baseQuery = this.metaCollection
139
+ const isForward = direction === "forward";
140
+ const sortDir = isForward ? "desc" : "asc";
141
+
142
+ // Firestore requires orderBy on inequality field (status) first
143
+ let query = this.metaCollection
102
144
  .where("group", "==", group)
103
- .where("status", "!=", "deleted");
104
-
105
- return this.executePaginatedQuery(
106
- baseQuery,
107
- locale,
108
- limit,
109
- cursor,
110
- direction,
111
- );
145
+ .where("status", "!=", "deleted")
146
+ .orderBy("status", sortDir)
147
+ .orderBy("createdAt", sortDir)
148
+ .orderBy(FieldPath.documentId(), sortDir);
149
+
150
+ if (cursor) {
151
+ const [timestamp, id] = cursorToFirestoreValues(cursor);
152
+ query = query.startAfter(timestamp, id);
153
+ }
154
+
155
+ const snapshot = await query.limit(limit + 1).get();
156
+ const hasMore = snapshot.docs.length > limit;
157
+ let docs = hasMore ? snapshot.docs.slice(0, -1) : snapshot.docs;
158
+
159
+ if (!isForward) {
160
+ docs = docs.reverse();
161
+ }
162
+
163
+ if (docs.length === 0) {
164
+ return {
165
+ data: [],
166
+ startCursor: null,
167
+ endCursor: null,
168
+ hasNextPage: false,
169
+ hasPreviousPage: false,
170
+ };
171
+ }
172
+
173
+ const entities = await this.hydrate(docs, locale);
174
+
175
+ const firstDoc = docs[0];
176
+ const lastDoc = docs[docs.length - 1];
177
+ const firstCreatedAt = firstDoc.get("createdAt") as Timestamp;
178
+ const lastCreatedAt = lastDoc.get("createdAt") as Timestamp;
179
+
180
+ return {
181
+ data: entities,
182
+ startCursor: encodeCursor(firstCreatedAt, firstDoc.id),
183
+ endCursor: encodeCursor(lastCreatedAt, lastDoc.id),
184
+ hasNextPage: isForward ? hasMore : !!cursor,
185
+ hasPreviousPage: isForward ? !!cursor : hasMore,
186
+ };
112
187
  }
113
188
  }