@cravery/firebase 0.0.17 → 0.0.19

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":"report.d.ts","sourceRoot":"","sources":["../../src/converter/report.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EAGvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAQ5C,eAAO,MAAM,eAAe,EAAE,sBAAsB,CAAC,MAAM,CAsC1D,CAAC"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/converter/report.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EAGvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAS5C,eAAO,MAAM,eAAe,EAAE,sBAAsB,CAAC,MAAM,CAsC1D,CAAC"}
@@ -16,7 +16,7 @@ const utils_1 = require("../utils");
16
16
  exports.reportConverter = {
17
17
  toFirestore(report) {
18
18
  const { id, createdAt, updatedAt, deletedAt, reviewedAt } = report, rest = __rest(report, ["id", "createdAt", "updatedAt", "deletedAt", "reviewedAt"]);
19
- return Object.assign(Object.assign({}, rest), { createdAt: (0, utils_1.toFirestoreTimestamp)(createdAt), updatedAt: (0, utils_1.toFirestoreTimestamp)(updatedAt), deletedAt: (0, utils_1.toOptionalFirestoreTimestamp)(deletedAt), reviewedAt: (0, utils_1.toOptionalFirestoreTimestamp)(reviewedAt) });
19
+ return (0, utils_1.stripUndefined)(Object.assign(Object.assign({}, rest), { createdAt: (0, utils_1.toFirestoreTimestamp)(createdAt), updatedAt: (0, utils_1.toFirestoreTimestamp)(updatedAt), deletedAt: (0, utils_1.toOptionalFirestoreTimestamp)(deletedAt), reviewedAt: (0, utils_1.toOptionalFirestoreTimestamp)(reviewedAt) }));
20
20
  },
21
21
  fromFirestore(snapshot) {
22
22
  const data = snapshot.data();
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/converter/report.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAMA,oCAKkB;AAEL,QAAA,eAAe,GAAmC;IAC7D,WAAW,CAAC,MAAc;QACxB,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,KAAc,MAAM,EAAf,IAAI,UAAK,MAAM,EAArE,2DAA4D,CAAS,CAAC;QAE5E,uCACK,IAAI,KACP,SAAS,EAAE,IAAA,4BAAoB,EAAC,SAAS,CAAC,EAC1C,SAAS,EAAE,IAAA,4BAAoB,EAAC,SAAS,CAAC,EAC1C,SAAS,EAAE,IAAA,oCAA4B,EAAC,SAAS,CAAC,EAClD,UAAU,EAAE,IAAA,oCAA4B,EAAC,UAAU,CAAC,IACpD;IACJ,CAAC;IAED,aAAa,CAAC,QAA+B;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE7B,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,UAAU,EAAE,IAAA,2BAAmB,EAAC,IAAI,CAAC,UAAU,CAAC;YAChD,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAA,mBAAW,EAAC,IAAI,CAAC,SAAS,CAAC;YACtC,SAAS,EAAE,IAAA,mBAAW,EAAC,IAAI,CAAC,SAAS,CAAC;YACtC,SAAS,EAAE,IAAA,2BAAmB,EAAC,IAAI,CAAC,SAAS,CAAC;SAC/C,CAAC;IACJ,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/converter/report.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAMA,oCAMkB;AAEL,QAAA,eAAe,GAAmC;IAC7D,WAAW,CAAC,MAAc;QACxB,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,KAAc,MAAM,EAAf,IAAI,UAAK,MAAM,EAArE,2DAA4D,CAAS,CAAC;QAE5E,OAAO,IAAA,sBAAc,kCAChB,IAAI,KACP,SAAS,EAAE,IAAA,4BAAoB,EAAC,SAAS,CAAC,EAC1C,SAAS,EAAE,IAAA,4BAAoB,EAAC,SAAS,CAAC,EAC1C,SAAS,EAAE,IAAA,oCAA4B,EAAC,SAAS,CAAC,EAClD,UAAU,EAAE,IAAA,oCAA4B,EAAC,UAAU,CAAC,IACpD,CAAC;IACL,CAAC;IAED,aAAa,CAAC,QAA+B;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE7B,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,UAAU,EAAE,IAAA,2BAAmB,EAAC,IAAI,CAAC,UAAU,CAAC;YAChD,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAA,mBAAW,EAAC,IAAI,CAAC,SAAS,CAAC;YACtC,SAAS,EAAE,IAAA,mBAAW,EAAC,IAAI,CAAC,SAAS,CAAC;YACtC,SAAS,EAAE,IAAA,2BAAmB,EAAC,IAAI,CAAC,SAAS,CAAC;SAC/C,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -3,5 +3,6 @@ export * from "./equipment";
3
3
  export * from "./ingredient";
4
4
  export * from "./recipe_stats";
5
5
  export * from "./recipe";
6
+ export * from "./report";
6
7
  export * from "./user_recipe";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC"}
@@ -19,5 +19,6 @@ __exportStar(require("./equipment"), exports);
19
19
  __exportStar(require("./ingredient"), exports);
20
20
  __exportStar(require("./recipe_stats"), exports);
21
21
  __exportStar(require("./recipe"), exports);
22
+ __exportStar(require("./report"), exports);
22
23
  __exportStar(require("./user_recipe"), exports);
23
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB;AACvB,8CAA4B;AAC5B,+CAA6B;AAC7B,iDAA+B;AAC/B,2CAAyB;AACzB,gDAA8B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB;AACvB,8CAA4B;AAC5B,+CAA6B;AAC7B,iDAA+B;AAC/B,2CAAyB;AACzB,2CAAyB;AACzB,gDAA8B"}
@@ -0,0 +1,14 @@
1
+ import { Firestore } from "firebase-admin/firestore";
2
+ import { type Report, type ReportTargetType } from "@cravery/core";
3
+ export declare class ReportRepository {
4
+ private db;
5
+ constructor(db: Firestore);
6
+ private get collection();
7
+ create(report: Omit<Report, "id" | "createdAt" | "updatedAt" | "deletedAt" | "status">): Promise<Report>;
8
+ getById(id: string): Promise<Report | null>;
9
+ getByUserId(userId: string, limit?: number): Promise<Report[]>;
10
+ getByTargetType(targetType: ReportTargetType, limit?: number): Promise<Report[]>;
11
+ getByTargetId(targetId: string): Promise<Report[]>;
12
+ updateStatus(id: string, reportStatus: Report["reportStatus"], reviewedBy?: string, resolution?: string): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/repository/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,gBAAgB,EAEtB,MAAM,eAAe,CAAC;AAGvB,qBAAa,gBAAgB;IACf,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,SAAS;IAEjC,OAAO,KAAK,UAAU,GAErB;IAEK,MAAM,CACV,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC,GAC9E,OAAO,CAAC,MAAM,CAAC;IAcZ,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK3C,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS1D,eAAe,CACnB,UAAU,EAAE,gBAAgB,EAC5B,KAAK,SAAK,GACT,OAAO,CAAC,MAAM,EAAE,CAAC;IASd,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQlD,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,CAAC,cAAc,CAAC,EACpC,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;CAiBjB"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReportRepository = void 0;
4
+ const firestore_1 = require("firebase-admin/firestore");
5
+ const core_1 = require("@cravery/core");
6
+ const converter_1 = require("../converter");
7
+ class ReportRepository {
8
+ constructor(db) {
9
+ this.db = db;
10
+ }
11
+ get collection() {
12
+ return this.db.collection(core_1.COLLECTIONS.Reports).withConverter(converter_1.reportConverter);
13
+ }
14
+ async create(report) {
15
+ const docRef = this.db.collection(core_1.COLLECTIONS.Reports).doc();
16
+ const now = firestore_1.Timestamp.now();
17
+ const newReport = Object.assign(Object.assign({}, report), { id: docRef.id, status: "active", createdAt: { seconds: now.seconds, nanoseconds: now.nanoseconds }, updatedAt: { seconds: now.seconds, nanoseconds: now.nanoseconds } });
18
+ await docRef.withConverter(converter_1.reportConverter).set(newReport);
19
+ return newReport;
20
+ }
21
+ async getById(id) {
22
+ const doc = await this.collection.doc(id).get();
23
+ return doc.exists ? doc.data() : null;
24
+ }
25
+ async getByUserId(userId, limit = 50) {
26
+ const snapshot = await this.collection
27
+ .where("userId", "==", userId)
28
+ .orderBy("createdAt", "desc")
29
+ .limit(limit)
30
+ .get();
31
+ return snapshot.docs.map((doc) => doc.data());
32
+ }
33
+ async getByTargetType(targetType, limit = 50) {
34
+ const snapshot = await this.collection
35
+ .where("targetType", "==", targetType)
36
+ .orderBy("createdAt", "desc")
37
+ .limit(limit)
38
+ .get();
39
+ return snapshot.docs.map((doc) => doc.data());
40
+ }
41
+ async getByTargetId(targetId) {
42
+ const snapshot = await this.collection
43
+ .where("targetId", "==", targetId)
44
+ .orderBy("createdAt", "desc")
45
+ .get();
46
+ return snapshot.docs.map((doc) => doc.data());
47
+ }
48
+ async updateStatus(id, reportStatus, reviewedBy, resolution) {
49
+ const updates = {
50
+ reportStatus,
51
+ updatedAt: firestore_1.Timestamp.now(),
52
+ };
53
+ if (reviewedBy) {
54
+ updates.reviewedBy = reviewedBy;
55
+ updates.reviewedAt = firestore_1.Timestamp.now();
56
+ }
57
+ if (resolution) {
58
+ updates.resolution = resolution;
59
+ }
60
+ await this.db.collection(core_1.COLLECTIONS.Reports).doc(id).update(updates);
61
+ }
62
+ }
63
+ exports.ReportRepository = ReportRepository;
64
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/repository/report.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.17",
3
+ "version": "0.0.19",
4
4
  "description": "Shared Firebase Admin SDK utilities for Cravery",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -54,6 +54,6 @@
54
54
  "src/**/*"
55
55
  ],
56
56
  "dependencies": {
57
- "@cravery/core": "^0.0.53"
57
+ "@cravery/core": "^0.0.54"
58
58
  }
59
59
  }
@@ -9,19 +9,20 @@ import {
9
9
  toOptionalTimestamp,
10
10
  toFirestoreTimestamp,
11
11
  toOptionalFirestoreTimestamp,
12
+ stripUndefined,
12
13
  } from "../utils";
13
14
 
14
15
  export const reportConverter: FirestoreDataConverter<Report> = {
15
16
  toFirestore(report: Report): DocumentData {
16
17
  const { id, createdAt, updatedAt, deletedAt, reviewedAt, ...rest } = report;
17
18
 
18
- return {
19
+ return stripUndefined({
19
20
  ...rest,
20
21
  createdAt: toFirestoreTimestamp(createdAt),
21
22
  updatedAt: toFirestoreTimestamp(updatedAt),
22
23
  deletedAt: toOptionalFirestoreTimestamp(deletedAt),
23
24
  reviewedAt: toOptionalFirestoreTimestamp(reviewedAt),
24
- };
25
+ });
25
26
  },
26
27
 
27
28
  fromFirestore(snapshot: QueryDocumentSnapshot): Report {
@@ -3,4 +3,5 @@ export * from "./equipment";
3
3
  export * from "./ingredient";
4
4
  export * from "./recipe_stats";
5
5
  export * from "./recipe";
6
+ export * from "./report";
6
7
  export * from "./user_recipe";
@@ -0,0 +1,89 @@
1
+ import { Firestore, Timestamp } from "firebase-admin/firestore";
2
+ import {
3
+ COLLECTIONS,
4
+ type Report,
5
+ type ReportTargetType,
6
+ type EntityStatus,
7
+ } from "@cravery/core";
8
+ import { reportConverter } from "../converter";
9
+
10
+ export class ReportRepository {
11
+ constructor(private db: Firestore) {}
12
+
13
+ private get collection() {
14
+ return this.db.collection(COLLECTIONS.Reports).withConverter(reportConverter);
15
+ }
16
+
17
+ async create(
18
+ report: Omit<Report, "id" | "createdAt" | "updatedAt" | "deletedAt" | "status">,
19
+ ): Promise<Report> {
20
+ const docRef = this.db.collection(COLLECTIONS.Reports).doc();
21
+ const now = Timestamp.now();
22
+ const newReport: Report = {
23
+ ...report,
24
+ id: docRef.id,
25
+ status: "active" as EntityStatus,
26
+ createdAt: { seconds: now.seconds, nanoseconds: now.nanoseconds },
27
+ updatedAt: { seconds: now.seconds, nanoseconds: now.nanoseconds },
28
+ };
29
+ await docRef.withConverter(reportConverter).set(newReport);
30
+ return newReport;
31
+ }
32
+
33
+ async getById(id: string): Promise<Report | null> {
34
+ const doc = await this.collection.doc(id).get();
35
+ return doc.exists ? doc.data()! : null;
36
+ }
37
+
38
+ async getByUserId(userId: string, limit = 50): Promise<Report[]> {
39
+ const snapshot = await this.collection
40
+ .where("userId", "==", userId)
41
+ .orderBy("createdAt", "desc")
42
+ .limit(limit)
43
+ .get();
44
+ return snapshot.docs.map((doc) => doc.data());
45
+ }
46
+
47
+ async getByTargetType(
48
+ targetType: ReportTargetType,
49
+ limit = 50,
50
+ ): Promise<Report[]> {
51
+ const snapshot = await this.collection
52
+ .where("targetType", "==", targetType)
53
+ .orderBy("createdAt", "desc")
54
+ .limit(limit)
55
+ .get();
56
+ return snapshot.docs.map((doc) => doc.data());
57
+ }
58
+
59
+ async getByTargetId(targetId: string): Promise<Report[]> {
60
+ const snapshot = await this.collection
61
+ .where("targetId", "==", targetId)
62
+ .orderBy("createdAt", "desc")
63
+ .get();
64
+ return snapshot.docs.map((doc) => doc.data());
65
+ }
66
+
67
+ async updateStatus(
68
+ id: string,
69
+ reportStatus: Report["reportStatus"],
70
+ reviewedBy?: string,
71
+ resolution?: string,
72
+ ): Promise<void> {
73
+ const updates: Partial<Report> & { updatedAt: Timestamp; reviewedAt?: Timestamp } = {
74
+ reportStatus,
75
+ updatedAt: Timestamp.now(),
76
+ };
77
+
78
+ if (reviewedBy) {
79
+ updates.reviewedBy = reviewedBy;
80
+ updates.reviewedAt = Timestamp.now();
81
+ }
82
+
83
+ if (resolution) {
84
+ updates.resolution = resolution;
85
+ }
86
+
87
+ await this.db.collection(COLLECTIONS.Reports).doc(id).update(updates);
88
+ }
89
+ }