Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1x 2x 2x 2x 1x 10x 10x 1x 1x | import { FieldValue, Timestamp } from '@angular/fire/firestore'; import type { FirestoreDataConverter, QueryDocumentSnapshot, SetOptions, SnapshotOptions, WithFieldValue, } from '@angular/fire/firestore'; import type { Quiz, QuizPayload } from './quiz.service'; /** Firestore DocumentData compatible model for the database. */ export interface QuizModel extends QuizPayload { /** Original creation date, not to be modified. */ readonly createdAt: Timestamp; /** Modification date, updated automatically by the converter. */ readonly updatedAt: Timestamp; } /** * FirestoreDataConverter uses WithFieldValue for toFirestore, which climbs inside of the Date object * and messes with all of the type signatures. So this method is over engineered to try and handle * that unlikely case that the date is neither a FieldValue nor a Date. */ const timestampFromDate = (date: FieldValue | WithFieldValue<Date>): FieldValue | WithFieldValue<Timestamp> => { Iif (date instanceof FieldValue) { return date; } if (date instanceof Date) { return Timestamp.fromDate(date); } // This will never be thrown since the `date` value is either a Date or a FieldValue (unless // something goes terribly wrong). I opened a ticket about how `WithFieldValue` mangles inner class // types: https://github.com/googleapis/nodejs-firestore/issues/2291 throw new TypeError(`Unknown type ${typeof date}`); }; /** * In order to set the types correctly on the CollectionReference we need to use a FirestoreDataConverter * to manipulate the types. * * At the same time we can perform other actions like converting Timestamps to Dates and adding the * document id. * * Note, using a Class here instead of an object makes the type checker more complicated and there * are a lot of complaints about not using `this` from the linter. Which is maybe a rule that I should * disable. */ export const quizConverter: FirestoreDataConverter<Quiz, QuizModel> = { /** * Convert the model from the database into the type expected by consumers. * Timestamps should all be converted into Dates. * Add the Document ID. */ fromFirestore: (snapshot: QueryDocumentSnapshot<QuizModel>, options: SnapshotOptions): Quiz => { const data = snapshot.data(options); return { ...data, id: snapshot.id, createdAt: data.createdAt.toDate(), updatedAt: data.updatedAt.toDate(), }; }, /** * This is a much less useful converter as it doesn't apply to updateDoc. * It's only purpose is to change the Type, if it wasn't here then things would work better but */ toFirestore: (quiz: WithFieldValue<Quiz>, _options?: SetOptions): WithFieldValue<QuizModel> => { const payload: WithFieldValue<QuizModel> = { ...quiz, createdAt: timestampFromDate(quiz.createdAt), updatedAt: timestampFromDate(quiz.updatedAt), }; return payload; }, }; |