firebase-admin-node
firebase-admin-node copied to clipboard
Allow generic in onDocumentUpdated, onDocumentCreated, etc...
Problem:
Making a wrapper class where types can be inferred is not possible.
Goal:
onDocumentUpdated<Payment>( // note the modified declaration below
`${Col.payments}/{paymentID}`,
handlers.authorizePayment,
);
with changes to the declaration such as:
// firestore.d.ts
export declare function onDocumentUpdated<Data extends DocumentData, Document extends string>(document: Document, handler: (event: FirestoreEvent<Change<QueryDocumentSnapshot<T>> | undefined, ParamsOf<Document>>) => any | Promise<any>): CloudFunction<FirestoreEvent<Change<QueryDocumentSnapshot> | undefined, ParamsOf<Document>>>;
Use case:
It will be possible to write things like:
export type UpdateEvent<T> = FirestoreEvent<Change<QueryDocumentSnapshot<T>> | undefined>;
class AuthorizePaymentOnValidatedTrigger implements OnUpdate<Payment> {
handle(event: UpdateEvent<Payment>) {
// ...
}
}
Currently I'm using a wrapper:
/// Used to create firebase triggers without having to cast
export abstract class Triggers {
static onDocumentUpdated<T extends Identifiable>(path: string, handler: OnUpdateHandler<T>) {
return onDocumentUpdated(path, (event) => handler.handle(event as UpdateEvent<T>));
}
static onDocumentCreated<T extends Identifiable>(path: string, handler: OnCreateHandler<T>) {
return onDocumentCreated(path, (event) => handler.handle(event as CreateEvent<T>));
}
static onDocumentDeleted<T extends Identifiable>(path: string, handler: OnDeleteHandler<T>) {
return onDocumentDeleted(path, (event) => handler.handle(event as DeleteEvent<T>));
}
}
export type UpdateEvent<T> = FirestoreEvent<Change<QueryDocumentSnapshot<T>>>;
export interface OnUpdateHandler<T extends Identifiable> {
handle(event: UpdateEvent<T>): Promise<void>;
}
export type CreateEvent<T> = FirestoreEvent<QueryDocumentSnapshot<T>>;
export interface OnCreateHandler<T extends Identifiable> {
handle(event: CreateEvent<T>): Promise<void>;
}
export type DeleteEvent<T> = FirestoreEvent<QueryDocumentSnapshot<T>>;
export interface OnDeleteHandler<T extends Identifiable> {
handle(deleted: DeleteEvent<T>): Promise<void>;
}
together with #2202 would allow:
handle(event: UpdateEvent<Payment>) {
const { before, after } = event.data;
}
instead of
handle(event: UpdateEvent) {
const data = event.data;
if (!data) return;
const before = data.before.data() as Payment;
const after = data.after.data() as Payment;
}