From bfc36df2919e6baa86fd8f8924d5b54449527e52 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Mon, 1 Apr 2024 13:45:58 -0400 Subject: [PATCH 01/12] rebasing --- spec/v2/providers/firestore.spec.ts | 190 ++++++++++++++++++++++++++ src/v2/providers/firestore.ts | 200 ++++++++++++++++++++++++++++ 2 files changed, 390 insertions(+) diff --git a/spec/v2/providers/firestore.spec.ts b/spec/v2/providers/firestore.spec.ts index e672703a6..77ed0aa1d 100644 --- a/spec/v2/providers/firestore.spec.ts +++ b/spec/v2/providers/firestore.spec.ts @@ -40,6 +40,8 @@ const eventBase = { datacontenttype: "application/protobuf", dataschema: "https://github.com/googleapis/google-cloudevents/blob/main/proto/google/events/cloud/firestore/v1/data.proto", + authtype: "unknown", + authid: "1234", id: "379ad868-5ef9-4c84-a8ba-f75f1b056663", source: "projects/my-project/databases/my-db/documents/d", subject: "documents/foo/fGRodw71mHutZ4wGDuT8", @@ -511,6 +513,194 @@ describe("firestore", () => { }); }); + describe("onDocumentWrittenWithAuthContext", () => { + it("should create a func", () => { + const expectedEp = makeExpectedEp( + firestore.writtenEventWithAuthContextType, + { + database: "(default)", + namespace: "(default)", + }, + { + document: "foo/{bar}", + } + ); + + const func = firestore.onDocumentWrittenWithAuthContext("foo/{bar}", () => 2); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + + it("should create a func with opts", () => { + const expectedEp = makeExpectedEp( + firestore.writtenEventWithAuthContextType, + { + database: "my-db", + namespace: "my-ns", + }, + { + document: "foo/{bar}", + } + ); + expectedEp["region"] = ["us-central1"]; + + const func = firestore.onDocumentWrittenWithAuthContext( + { + region: "us-central1", + document: "foo/{bar}", + database: "my-db", + namespace: "my-ns", + }, + () => 2 + ); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + }); + + describe("onDocumentCreatedWithAuthContext", () => { + it("should create a func", () => { + const expectedEp = makeExpectedEp( + firestore.createdEventWithAuthContextType, + { + database: "(default)", + namespace: "(default)", + }, + { + document: "foo/{bar}", + } + ); + + const func = firestore.onDocumentCreatedWithAuthContext("foo/{bar}", () => 2); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + + it("should create a func with opts", () => { + const expectedEp = makeExpectedEp( + firestore.createdEventWithAuthContextType, + { + database: "my-db", + namespace: "my-ns", + }, + { + document: "foo/{bar}", + } + ); + expectedEp["region"] = ["us-central1"]; + + const func = firestore.onDocumentCreatedWithAuthContext( + { + region: "us-central1", + document: "foo/{bar}", + database: "my-db", + namespace: "my-ns", + }, + () => 2 + ); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + }); + + describe("onDocumentUpdatedWithAuthContext", () => { + it("should create a func", () => { + const expectedEp = makeExpectedEp( + firestore.updatedEventWithAuthContextType, + { + database: "(default)", + namespace: "(default)", + }, + { + document: "foo/{bar}", + } + ); + + const func = firestore.onDocumentUpdatedWithAuthContext("foo/{bar}", () => 2); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + + it("should create a func with opts", () => { + const expectedEp = makeExpectedEp( + firestore.updatedEventWithAuthContextType, + { + database: "my-db", + namespace: "my-ns", + }, + { + document: "foo/{bar}", + } + ); + expectedEp["region"] = ["us-central1"]; + + const func = firestore.onDocumentUpdatedWithAuthContext( + { + region: "us-central1", + document: "foo/{bar}", + database: "my-db", + namespace: "my-ns", + }, + () => 2 + ); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + }); + + describe("onDocumentDeletedWithAuthContext", () => { + it("should create a func", () => { + const expectedEp = makeExpectedEp( + firestore.deletedEventWithAuthContextType, + { + database: "(default)", + namespace: "(default)", + }, + { + document: "foo/{bar}", + } + ); + + const func = firestore.onDocumentDeletedWithAuthContext("foo/{bar}", () => 2); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + + it("should create a func with opts", () => { + const expectedEp = makeExpectedEp( + firestore.deletedEventWithAuthContextType, + { + database: "my-db", + namespace: "my-ns", + }, + { + document: "foo/{bar}", + } + ); + expectedEp["region"] = ["us-central1"]; + + const func = firestore.onDocumentDeletedWithAuthContext( + { + region: "us-central1", + document: "foo/{bar}", + database: "my-db", + namespace: "my-ns", + }, + () => 2 + ); + + expect(func.run(true as any)).to.eq(2); + expect(func.__endpoint).to.deep.eq(expectedEp); + }); + }); + describe("getOpts", () => { it("should handle document string", () => { const { document, database, namespace, opts } = firestore.getOpts("foo/{bar}"); diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index cc78aa87f..c6e3e45db 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -52,6 +52,22 @@ export const updatedEventType = "google.cloud.firestore.document.v1.updated"; /** @internal */ export const deletedEventType = "google.cloud.firestore.document.v1.deleted"; +/** @internal */ +export const writtenEventWithAuthContextType = + "google.cloud.firestore.document.v1.written.withAuthContext"; + +/** @internal */ +export const createdEventWithAuthContextType = + "google.cloud.firestore.document.v1.created.withAuthContext"; + +/** @internal */ +export const updatedEventWithAuthContextType = + "google.cloud.firestore.document.v1.updated.withAuthContext"; + +/** @internal */ +export const deletedEventWithAuthContextType = + "google.cloud.firestore.document.v1.deleted.withAuthContext"; + // https://github.com/googleapis/google-cloudevents-nodejs/blob/main/cloud/firestore/v1/DocumentEventData.ts /** @internal */ export interface RawFirestoreDocument { @@ -77,6 +93,8 @@ export interface RawFirestoreEvent extends CloudEvent */ export interface FirestoreEvent> extends CloudEvent { /** The location of the Firestore instance */ @@ -97,6 +117,10 @@ export interface FirestoreEvent> extends Clou namespace: string; /** The document path */ document: string; + /** The type of principal that triggered the event */ + authType?: AuthType; + /** The unique identifier for the principal */ + authId?: string; /** * An object containing the values of the path patterns. * Only named capture groups will be populated - {key}, {key=*}, {key=**} @@ -155,6 +179,50 @@ export function onDocumentWritten( return onChangedOperation(writtenEventType, documentOrOpts, handler); } +/** + * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param document - The Firestore document path to trigger on. + * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. + */ +export function onDocumentWrittenWithAuthContext( + document: Document, + handler: ( + event: FirestoreEvent | undefined, ParamsOf> + ) => any | Promise +): CloudFunction | undefined, ParamsOf>>; + +/** + * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param opts - Options that can be set on an individual event-handling function. + * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. + */ +export function onDocumentWrittenWithAuthContext( + opts: DocumentOptions, + handler: ( + event: FirestoreEvent | undefined, ParamsOf> + ) => any | Promise +): CloudFunction | undefined, ParamsOf>>; + +/** + * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param opts - Options or a string document path. + * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. + */ +export function onDocumentWrittenWithAuthContext( + documentorOpts: Document | DocumentOptions, + handler: ( + event: FirestoreEvent | undefined, ParamsOf> + ) => any | Promise +): CloudFunction | undefined, ParamsOf>> { + return onChangedOperation(writtenEventWithAuthContextType, documentorOpts, handler); +} + /** * Event handler which triggers when a document is created in Firestore. * @@ -196,6 +264,49 @@ export function onDocumentCreated( return onOperation(createdEventType, documentOrOpts, handler); } +/** + * Event handler which triggers when a document is created in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param document - The Firestore document path to trigger on. + * @param handler - Event handler which is run every time a Firestore create occurs. + */ +export function onDocumentCreatedWithAuthContext( + document: Document, + handler: ( + event: FirestoreEvent> + ) => any | Promise +): CloudFunction>>; + +/** + * Event handler which triggers when a document is created in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param opts - Options that can be set on an individual event-handling function. + * @param handler - Event handler which is run every time a Firestore create occurs. + */ +export function onDocumentCreatedWithAuthContext( + opts: DocumentOptions, + handler: ( + event: FirestoreEvent> + ) => any | Promise +): CloudFunction>>; + +/** + * Event handler which triggers when a document is created in Firestore. + * + * @param documentOrOpts - Options or a string document path. + * @param handler - Event handler which is run every time a Firestore create occurs. + */ +export function onDocumentCreatedWithAuthContext( + documentOrOpts: Document | DocumentOptions, + handler: ( + event: FirestoreEvent> + ) => any | Promise +): CloudFunction>> { + return onOperation(createdEventWithAuthContextType, documentOrOpts, handler); +} + /** * Event handler which triggers when a document is updated in Firestore. * @@ -236,6 +347,48 @@ export function onDocumentUpdated( return onChangedOperation(updatedEventType, documentOrOpts, handler); } +/** + * Event handler which triggers when a document is updated in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param document - The Firestore document path to trigger on. + * @param handler - Event handler which is run every time a Firestore update occurs. + */ +export function onDocumentUpdatedWithAuthContext( + document: Document, + handler: ( + event: FirestoreEvent | undefined, ParamsOf> + ) => any | Promise +): CloudFunction | undefined, ParamsOf>>; +/** + * Event handler which triggers when a document is updated in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param opts - Options that can be set on an individual event-handling function. + * @param handler - Event handler which is run every time a Firestore update occurs. + */ +export function onDocumentUpdatedWithAuthContext( + opts: DocumentOptions, + handler: ( + event: FirestoreEvent | undefined, ParamsOf> + ) => any | Promise +): CloudFunction | undefined, ParamsOf>>; + +/** + * Event handler which triggers when a document is updated in Firestore. + * + * @param documentOrOpts - Options or a string document path. + * @param handler - Event handler which is run every time a Firestore update occurs. + */ +export function onDocumentUpdatedWithAuthContext( + documentOrOpts: Document | DocumentOptions, + handler: ( + event: FirestoreEvent | undefined, ParamsOf> + ) => any | Promise +): CloudFunction | undefined, ParamsOf>> { + return onChangedOperation(updatedEventWithAuthContextType, documentOrOpts, handler); +} + /** * Event handler which triggers when a document is deleted in Firestore. * @@ -277,6 +430,49 @@ export function onDocumentDeleted( return onOperation(deletedEventType, documentOrOpts, handler); } +/** + * Event handler which triggers when a document is deleted in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param document - The Firestore document path to trigger on. + * @param handler - Event handler which is run every time a Firestore delete occurs. + */ +export function onDocumentDeletedWithAuthContext( + document: Document, + handler: ( + event: FirestoreEvent> + ) => any | Promise +): CloudFunction>>; + +/** + * Event handler which triggers when a document is deleted in Firestore. + * This trigger will also provide the authentication context of the principal who triggered the event. + * + * @param opts - Options that can be set on an individual event-handling function. + * @param handler - Event handler which is run every time a Firestore delete occurs. + */ +export function onDocumentDeletedWithAuthContext( + opts: DocumentOptions, + handler: ( + event: FirestoreEvent> + ) => any | Promise +): CloudFunction>>; + +/** + * Event handler which triggers when a document is deleted in Firestore. + * + * @param documentOrOpts - Options or a string document path. + * @param handler - Event handler which is run every time a Firestore delete occurs. + */ +export function onDocumentDeletedWithAuthContext( + documentOrOpts: Document | DocumentOptions, + handler: ( + event: FirestoreEvent> + ) => any | Promise +): CloudFunction>> { + return onOperation(deletedEventWithAuthContextType, documentOrOpts, handler); +} + /** @internal */ export function getOpts(documentOrOpts: string | DocumentOptions) { let document: string | Expression; @@ -374,6 +570,8 @@ export function makeFirestoreEvent( ...event, params, data, + authType: event.authtype as AuthType, + authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; @@ -392,6 +590,8 @@ export function makeChangedFirestoreEvent( ...event, params, data, + authType: event.authtype as AuthType, + authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; From b6606018343fcd62048498625f1ce56a39c61837 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Thu, 1 Feb 2024 13:32:17 -0500 Subject: [PATCH 02/12] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb..fdbf13bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- Add new 2nd gen Firestore auth context triggers. (#1519) From 1184a58c3a47cca3c8f8d26e46d2515677a839e1 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Mon, 1 Apr 2024 12:30:54 -0400 Subject: [PATCH 03/12] update docstrings --- src/v2/providers/firestore.ts | 48 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index c6e3e45db..55efcce2d 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -139,7 +139,7 @@ export interface DocumentOptions extends Event } /** - * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * Event handler that triggers when a document is created, updated, or deleted in Firestore. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. @@ -152,7 +152,7 @@ export function onDocumentWritten( ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * Event handler that triggers when a document is created, updated, or deleted in Firestore. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. @@ -165,7 +165,7 @@ export function onDocumentWritten( ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * Event handler that triggers when a document is created, updated, or deleted in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. @@ -180,7 +180,7 @@ export function onDocumentWritten( } /** - * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * Event handler that triggers when a document is created, updated, or deleted in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. @@ -194,7 +194,7 @@ export function onDocumentWrittenWithAuthContext( ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * Event handler that triggers when a document is created, updated, or deleted in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. @@ -208,7 +208,7 @@ export function onDocumentWrittenWithAuthContext( ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is created, updated, or deleted in Firestore. + * Event handler that triggers when a document is created, updated, or deleted in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param opts - Options or a string document path. @@ -224,7 +224,7 @@ export function onDocumentWrittenWithAuthContext( } /** - * Event handler which triggers when a document is created in Firestore. + * Event handler that triggers when a document is created in Firestore. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore create occurs. @@ -237,7 +237,7 @@ export function onDocumentCreated( ): CloudFunction>>; /** - * Event handler which triggers when a document is created in Firestore. + * Event handler that triggers when a document is created in Firestore. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore create occurs. @@ -250,7 +250,7 @@ export function onDocumentCreated( ): CloudFunction>>; /** - * Event handler which triggers when a document is created in Firestore. + * Event handler that triggers when a document is created in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore create occurs. @@ -265,7 +265,7 @@ export function onDocumentCreated( } /** - * Event handler which triggers when a document is created in Firestore. + * Event handler that triggers when a document is created in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. @@ -279,7 +279,7 @@ export function onDocumentCreatedWithAuthContext( ): CloudFunction>>; /** - * Event handler which triggers when a document is created in Firestore. + * Event handler that triggers when a document is created in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. @@ -293,7 +293,7 @@ export function onDocumentCreatedWithAuthContext( ): CloudFunction>>; /** - * Event handler which triggers when a document is created in Firestore. + * Event handler that triggers when a document is created in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore create occurs. @@ -308,7 +308,7 @@ export function onDocumentCreatedWithAuthContext( } /** - * Event handler which triggers when a document is updated in Firestore. + * Event handler that triggers when a document is updated in Firestore. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore update occurs. @@ -320,7 +320,7 @@ export function onDocumentUpdated( ) => any | Promise ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is updated in Firestore. + * Event handler that triggers when a document is updated in Firestore. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore update occurs. @@ -333,7 +333,7 @@ export function onDocumentUpdated( ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is updated in Firestore. + * Event handler that triggers when a document is updated in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore update occurs. @@ -348,7 +348,7 @@ export function onDocumentUpdated( } /** - * Event handler which triggers when a document is updated in Firestore. + * Event handler that triggers when a document is updated in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. @@ -361,7 +361,7 @@ export function onDocumentUpdatedWithAuthContext( ) => any | Promise ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is updated in Firestore. + * Event handler that triggers when a document is updated in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. @@ -375,7 +375,7 @@ export function onDocumentUpdatedWithAuthContext( ): CloudFunction | undefined, ParamsOf>>; /** - * Event handler which triggers when a document is updated in Firestore. + * Event handler that triggers when a document is updated in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore update occurs. @@ -390,7 +390,7 @@ export function onDocumentUpdatedWithAuthContext( } /** - * Event handler which triggers when a document is deleted in Firestore. + * Event handler that triggers when a document is deleted in Firestore. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore delete occurs. @@ -403,7 +403,7 @@ export function onDocumentDeleted( ): CloudFunction>>; /** - * Event handler which triggers when a document is deleted in Firestore. + * Event handler that triggers when a document is deleted in Firestore. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore delete occurs. @@ -416,7 +416,7 @@ export function onDocumentDeleted( ): CloudFunction>>; /** - * Event handler which triggers when a document is deleted in Firestore. + * Event handler that triggers when a document is deleted in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore delete occurs. @@ -431,7 +431,7 @@ export function onDocumentDeleted( } /** - * Event handler which triggers when a document is deleted in Firestore. + * Event handler that triggers when a document is deleted in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. @@ -445,7 +445,7 @@ export function onDocumentDeletedWithAuthContext( ): CloudFunction>>; /** - * Event handler which triggers when a document is deleted in Firestore. + * Event handler that triggers when a document is deleted in Firestore. * This trigger will also provide the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. @@ -459,7 +459,7 @@ export function onDocumentDeletedWithAuthContext( ): CloudFunction>>; /** - * Event handler which triggers when a document is deleted in Firestore. + * Event handler that triggers when a document is deleted in Firestore. * * @param documentOrOpts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore delete occurs. From 5204b0dde3812c67bbfc65d256b5124e033fb25c Mon Sep 17 00:00:00 2001 From: Brian Li Date: Mon, 1 Apr 2024 12:32:47 -0400 Subject: [PATCH 04/12] update docstrings (again) --- src/v2/providers/firestore.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index 55efcce2d..72894be19 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -181,7 +181,7 @@ export function onDocumentWritten( /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. @@ -195,7 +195,7 @@ export function onDocumentWrittenWithAuthContext( /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. @@ -209,7 +209,7 @@ export function onDocumentWrittenWithAuthContext( /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param opts - Options or a string document path. * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. @@ -266,7 +266,7 @@ export function onDocumentCreated( /** * Event handler that triggers when a document is created in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore create occurs. @@ -280,7 +280,7 @@ export function onDocumentCreatedWithAuthContext( /** * Event handler that triggers when a document is created in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore create occurs. @@ -349,7 +349,7 @@ export function onDocumentUpdated( /** * Event handler that triggers when a document is updated in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore update occurs. @@ -362,7 +362,7 @@ export function onDocumentUpdatedWithAuthContext( ): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is updated in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore update occurs. @@ -432,7 +432,7 @@ export function onDocumentDeleted( /** * Event handler that triggers when a document is deleted in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param document - The Firestore document path to trigger on. * @param handler - Event handler which is run every time a Firestore delete occurs. @@ -446,7 +446,7 @@ export function onDocumentDeletedWithAuthContext( /** * Event handler that triggers when a document is deleted in Firestore. - * This trigger will also provide the authentication context of the principal who triggered the event. + * This trigger also provides the authentication context of the principal who triggered the event. * * @param opts - Options that can be set on an individual event-handling function. * @param handler - Event handler which is run every time a Firestore delete occurs. From b28d3d830ad53da16e4a8bf7797842d1bdf2ee67 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Mon, 1 Apr 2024 13:40:46 -0400 Subject: [PATCH 05/12] export authtype and add comment --- src/v2/providers/firestore.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index 72894be19..2afcfc332 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -103,7 +103,15 @@ export type DocumentSnapshot = firestore.DocumentSnapshot; /** A Firestore QueryDocumentSnapshot */ export type QueryDocumentSnapshot = firestore.QueryDocumentSnapshot; -type AuthType = "service_account" | "api_key" | "system" | "unauthenticated" | "unknown"; +/** + * AuthType defines the possible values for the authType field in a Firestore event with auth context. + * - service_account: a non-user principal used to identify a workload or machine user. + * - api_key: a non-user client API key. + * - system: an obscured identity used when Cloud Platform or another system triggered the event. Examples include a database record which was deleted based on a TTL. + * - unauthenticated: an unauthenticated action. + * - unknown: a general type to capture all other principals not captured in the other auth types. + */ +export type AuthType = "service_account" | "api_key" | "system" | "unauthenticated" | "unknown"; /** A CloudEvent that contains a DocumentSnapshot or a Change */ export interface FirestoreEvent> extends CloudEvent { From 0c518617bdc162512a293df80b5055df4ddb474e Mon Sep 17 00:00:00 2001 From: Brian Li Date: Mon, 1 Apr 2024 14:12:29 -0400 Subject: [PATCH 06/12] post rebase --- package-lock.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 6a51af0a1..9f23b098b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "@types/express": "4.17.3", "cors": "^2.8.5", "express": "^4.17.1", - "node-fetch": "^2.6.7", "protobufjs": "^7.2.2" }, "bin": { From aa8df0f767c67e0942b73cf8c43f77093ef73d32 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Wed, 3 Apr 2024 11:16:43 -0400 Subject: [PATCH 07/12] separate out event type with auth context --- spec/v2/providers/firestore.spec.ts | 68 +++++++++++ src/v2/providers/firestore.ts | 175 ++++++++++++++++++++++------ 2 files changed, 209 insertions(+), 34 deletions(-) diff --git a/spec/v2/providers/firestore.spec.ts b/spec/v2/providers/firestore.spec.ts index 77ed0aa1d..936e9d74f 100644 --- a/spec/v2/providers/firestore.spec.ts +++ b/spec/v2/providers/firestore.spec.ts @@ -558,6 +558,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentWrittenWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("onDocumentCreatedWithAuthContext", () => { @@ -605,6 +622,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentCreatedWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("onDocumentUpdatedWithAuthContext", () => { @@ -652,6 +686,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentUpdatedWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("onDocumentDeletedWithAuthContext", () => { @@ -699,6 +750,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentDeletedWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("getOpts", () => { diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index 2afcfc332..bfe5797ae 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -125,10 +125,6 @@ export interface FirestoreEvent> extends Clou namespace: string; /** The document path */ document: string; - /** The type of principal that triggered the event */ - authType?: AuthType; - /** The unique identifier for the principal */ - authId?: string; /** * An object containing the values of the path patterns. * Only named capture groups will be populated - {key}, {key=*}, {key=**} @@ -136,6 +132,15 @@ export interface FirestoreEvent> extends Clou params: Params; } +/** A CloudEvent that extends the Firestore event with auth context fields. */ +export interface FirestoreEventWithAuthContext> + extends FirestoreEvent { + /** The type of principal that triggered the event */ + authType: AuthType; + /** The unique identifier for the principal */ + authId?: string; +} + /** DocumentOptions extend EventHandlerOptions with provided document and optional database and namespace. */ export interface DocumentOptions extends EventHandlerOptions { /** The document path */ @@ -197,10 +202,11 @@ export function onDocumentWritten( export function onDocumentWrittenWithAuthContext( document: Document, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreEventWithAuthContext | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; - +): CloudFunction< + FirestoreEventWithAuthContext | undefined, ParamsOf> +>; /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. * This trigger also provides the authentication context of the principal who triggered the event. @@ -211,9 +217,11 @@ export function onDocumentWrittenWithAuthContext( export function onDocumentWrittenWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreEventWithAuthContext | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction< + FirestoreEventWithAuthContext | undefined, ParamsOf> +>; /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. @@ -225,10 +233,16 @@ export function onDocumentWrittenWithAuthContext( export function onDocumentWrittenWithAuthContext( documentorOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreEventWithAuthContext | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>> { - return onChangedOperation(writtenEventWithAuthContextType, documentorOpts, handler); +): CloudFunction< + FirestoreEventWithAuthContext | undefined, ParamsOf> +> { + return onChangedWithAuthContextOperation( + writtenEventWithAuthContextType, + documentorOpts, + handler + ); } /** @@ -282,9 +296,11 @@ export function onDocumentCreated( export function onDocumentCreatedWithAuthContext( document: Document, handler: ( - event: FirestoreEvent> + event: FirestoreEventWithAuthContext> ) => any | Promise -): CloudFunction>>; +): CloudFunction< + FirestoreEventWithAuthContext> +>; /** * Event handler that triggers when a document is created in Firestore. @@ -296,9 +312,11 @@ export function onDocumentCreatedWithAuthContext( export function onDocumentCreatedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreEventWithAuthContext> ) => any | Promise -): CloudFunction>>; +): CloudFunction< + FirestoreEventWithAuthContext> +>; /** * Event handler that triggers when a document is created in Firestore. @@ -309,9 +327,11 @@ export function onDocumentCreatedWithAuthContext( export function onDocumentCreatedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreEventWithAuthContext> ) => any | Promise -): CloudFunction>> { +): CloudFunction< + FirestoreEventWithAuthContext> +> { return onOperation(createdEventWithAuthContextType, documentOrOpts, handler); } @@ -365,9 +385,14 @@ export function onDocumentUpdated( export function onDocumentUpdatedWithAuthContext( document: Document, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreEventWithAuthContext< + Change | undefined, + ParamsOf + > ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction< + FirestoreEventWithAuthContext | undefined, ParamsOf> +>; /** * Event handler that triggers when a document is updated in Firestore. * This trigger also provides the authentication context of the principal who triggered the event. @@ -378,9 +403,14 @@ export function onDocumentUpdatedWithAuthContext( export function onDocumentUpdatedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreEventWithAuthContext< + Change | undefined, + ParamsOf + > ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction< + FirestoreEventWithAuthContext | undefined, ParamsOf> +>; /** * Event handler that triggers when a document is updated in Firestore. @@ -391,10 +421,19 @@ export function onDocumentUpdatedWithAuthContext( export function onDocumentUpdatedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreEventWithAuthContext< + Change | undefined, + ParamsOf + > ) => any | Promise -): CloudFunction | undefined, ParamsOf>> { - return onChangedOperation(updatedEventWithAuthContextType, documentOrOpts, handler); +): CloudFunction< + FirestoreEventWithAuthContext | undefined, ParamsOf> +> { + return onChangedWithAuthContextOperation( + updatedEventWithAuthContextType, + documentOrOpts, + handler + ); } /** @@ -448,9 +487,11 @@ export function onDocumentDeleted( export function onDocumentDeletedWithAuthContext( document: Document, handler: ( - event: FirestoreEvent> + event: FirestoreEventWithAuthContext> ) => any | Promise -): CloudFunction>>; +): CloudFunction< + FirestoreEventWithAuthContext> +>; /** * Event handler that triggers when a document is deleted in Firestore. @@ -462,9 +503,11 @@ export function onDocumentDeletedWithAuthContext( export function onDocumentDeletedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreEventWithAuthContext> ) => any | Promise -): CloudFunction>>; +): CloudFunction< + FirestoreEventWithAuthContext> +>; /** * Event handler that triggers when a document is deleted in Firestore. @@ -475,9 +518,11 @@ export function onDocumentDeletedWithAuthContext( export function onDocumentDeletedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreEventWithAuthContext> ) => any | Promise -): CloudFunction>> { +): CloudFunction< + FirestoreEventWithAuthContext> +> { return onOperation(deletedEventWithAuthContextType, documentOrOpts, handler); } @@ -568,7 +613,9 @@ export function makeFirestoreEvent( eventType: string, event: RawFirestoreEvent, params: Params -): FirestoreEvent { +): + | FirestoreEventWithAuthContext + | FirestoreEvent { const data = event.data ? eventType === createdEventType ? createSnapshot(event) @@ -578,11 +625,20 @@ export function makeFirestoreEvent( ...event, params, data, - authType: event.authtype as AuthType, - authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; + + if (event.authtype) { + const eventWithAuthContext = { + ...firestoreEvent, + authType: event.authtype as AuthType, + authId: event.authid, + }; + delete (eventWithAuthContext as any).authtype; + delete (eventWithAuthContext as any).authid; + return eventWithAuthContext; + } return firestoreEvent; } @@ -598,11 +654,34 @@ export function makeChangedFirestoreEvent( ...event, params, data, + }; + delete (firestoreEvent as any).datacontenttype; + delete (firestoreEvent as any).dataschema; + return firestoreEvent; +} + +/** @internal */ +export function makeChangedFirestoreEventWithAuthContext( + event: RawFirestoreEvent, + params: Params +): FirestoreEventWithAuthContext | undefined, Params> { + const data = event.data + ? Change.fromObjects(createBeforeSnapshot(event), createSnapshot(event)) + : undefined; + const firestoreEvent: FirestoreEventWithAuthContext< + Change | undefined, + Params + > = { + ...event, + params, + data, authType: event.authtype as AuthType, authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; + delete (firestoreEvent as any).authtype; + delete (firestoreEvent as any).authid; return firestoreEvent; } @@ -701,3 +780,31 @@ export function onChangedOperation( return func; } + +/** @internal */ +export function onChangedWithAuthContextOperation( + eventType: string, + documentOrOpts: Document | DocumentOptions, + handler: ( + event: FirestoreEventWithAuthContext, ParamsOf> + ) => any | Promise +): CloudFunction, ParamsOf>> { + const { document, database, namespace, opts } = getOpts(documentOrOpts); + + // wrap the handler + const func = (raw: CloudEvent) => { + const event = raw as RawFirestoreEvent; + const documentPattern = new PathPattern( + typeof document === "string" ? document : document.value() + ); + const params = makeParams(event.document, documentPattern) as unknown as ParamsOf; + const firestoreEvent = makeChangedFirestoreEventWithAuthContext(event, params); + return wrapTraceContext(withInit(handler))(firestoreEvent); + }; + + func.run = handler; + + func.__endpoint = makeEndpoint(eventType, opts, document, database, namespace); + + return func; +} From c5bda98ae70fb3024532807cfdc21190ee6e3b8c Mon Sep 17 00:00:00 2001 From: Brian Li Date: Wed, 3 Apr 2024 17:54:05 -0400 Subject: [PATCH 08/12] Revert "post rebase" This reverts commit 0c518617bdc162512a293df80b5055df4ddb474e. --- package-lock.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package-lock.json b/package-lock.json index 9f23b098b..6a51af0a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@types/express": "4.17.3", "cors": "^2.8.5", "express": "^4.17.1", + "node-fetch": "^2.6.7", "protobufjs": "^7.2.2" }, "bin": { From 92853d5e2a535fdec19dc6049ade4967d9e9f4bb Mon Sep 17 00:00:00 2001 From: Brian Li Date: Mon, 1 Apr 2024 14:12:29 -0400 Subject: [PATCH 09/12] post rebase --- package-lock.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 6a51af0a1..9f23b098b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "@types/express": "4.17.3", "cors": "^2.8.5", "express": "^4.17.1", - "node-fetch": "^2.6.7", "protobufjs": "^7.2.2" }, "bin": { From 8c83dd8415739c6a3dc824eead6c8ab2e317cca2 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Wed, 3 Apr 2024 17:56:54 -0400 Subject: [PATCH 10/12] Revert "separate out event type with auth context" This reverts commit aa8df0f767c67e0942b73cf8c43f77093ef73d32. --- spec/v2/providers/firestore.spec.ts | 68 ----------- src/v2/providers/firestore.ts | 175 ++++++---------------------- 2 files changed, 34 insertions(+), 209 deletions(-) diff --git a/spec/v2/providers/firestore.spec.ts b/spec/v2/providers/firestore.spec.ts index 936e9d74f..77ed0aa1d 100644 --- a/spec/v2/providers/firestore.spec.ts +++ b/spec/v2/providers/firestore.spec.ts @@ -558,23 +558,6 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); - - it("calls init function", async () => { - const event: firestore.RawFirestoreEvent = { - ...eventBase, - datacontenttype: "application/json", - data: { - oldValue: null, - value: null, - }, - }; - - let hello; - onInit(() => (hello = "world")); - expect(hello).to.be.undefined; - await firestore.onDocumentWrittenWithAuthContext("path", () => null)(event); - expect(hello).to.equal("world"); - }); }); describe("onDocumentCreatedWithAuthContext", () => { @@ -622,23 +605,6 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); - - it("calls init function", async () => { - const event: firestore.RawFirestoreEvent = { - ...eventBase, - datacontenttype: "application/json", - data: { - oldValue: null, - value: null, - }, - }; - - let hello; - onInit(() => (hello = "world")); - expect(hello).to.be.undefined; - await firestore.onDocumentCreatedWithAuthContext("path", () => null)(event); - expect(hello).to.equal("world"); - }); }); describe("onDocumentUpdatedWithAuthContext", () => { @@ -686,23 +652,6 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); - - it("calls init function", async () => { - const event: firestore.RawFirestoreEvent = { - ...eventBase, - datacontenttype: "application/json", - data: { - oldValue: null, - value: null, - }, - }; - - let hello; - onInit(() => (hello = "world")); - expect(hello).to.be.undefined; - await firestore.onDocumentUpdatedWithAuthContext("path", () => null)(event); - expect(hello).to.equal("world"); - }); }); describe("onDocumentDeletedWithAuthContext", () => { @@ -750,23 +699,6 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); - - it("calls init function", async () => { - const event: firestore.RawFirestoreEvent = { - ...eventBase, - datacontenttype: "application/json", - data: { - oldValue: null, - value: null, - }, - }; - - let hello; - onInit(() => (hello = "world")); - expect(hello).to.be.undefined; - await firestore.onDocumentDeletedWithAuthContext("path", () => null)(event); - expect(hello).to.equal("world"); - }); }); describe("getOpts", () => { diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index bfe5797ae..2afcfc332 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -125,6 +125,10 @@ export interface FirestoreEvent> extends Clou namespace: string; /** The document path */ document: string; + /** The type of principal that triggered the event */ + authType?: AuthType; + /** The unique identifier for the principal */ + authId?: string; /** * An object containing the values of the path patterns. * Only named capture groups will be populated - {key}, {key=*}, {key=**} @@ -132,15 +136,6 @@ export interface FirestoreEvent> extends Clou params: Params; } -/** A CloudEvent that extends the Firestore event with auth context fields. */ -export interface FirestoreEventWithAuthContext> - extends FirestoreEvent { - /** The type of principal that triggered the event */ - authType: AuthType; - /** The unique identifier for the principal */ - authId?: string; -} - /** DocumentOptions extend EventHandlerOptions with provided document and optional database and namespace. */ export interface DocumentOptions extends EventHandlerOptions { /** The document path */ @@ -202,11 +197,10 @@ export function onDocumentWritten( export function onDocumentWrittenWithAuthContext( document: Document, handler: ( - event: FirestoreEventWithAuthContext | undefined, ParamsOf> + event: FirestoreEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext | undefined, ParamsOf> ->; +): CloudFunction | undefined, ParamsOf>>; + /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. * This trigger also provides the authentication context of the principal who triggered the event. @@ -217,11 +211,9 @@ export function onDocumentWrittenWithAuthContext( export function onDocumentWrittenWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext | undefined, ParamsOf> + event: FirestoreEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext | undefined, ParamsOf> ->; +): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. @@ -233,16 +225,10 @@ export function onDocumentWrittenWithAuthContext( export function onDocumentWrittenWithAuthContext( documentorOpts: Document | DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext | undefined, ParamsOf> + event: FirestoreEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext | undefined, ParamsOf> -> { - return onChangedWithAuthContextOperation( - writtenEventWithAuthContextType, - documentorOpts, - handler - ); +): CloudFunction | undefined, ParamsOf>> { + return onChangedOperation(writtenEventWithAuthContextType, documentorOpts, handler); } /** @@ -296,11 +282,9 @@ export function onDocumentCreated( export function onDocumentCreatedWithAuthContext( document: Document, handler: ( - event: FirestoreEventWithAuthContext> + event: FirestoreEvent> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext> ->; +): CloudFunction>>; /** * Event handler that triggers when a document is created in Firestore. @@ -312,11 +296,9 @@ export function onDocumentCreatedWithAuthContext( export function onDocumentCreatedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext> + event: FirestoreEvent> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext> ->; +): CloudFunction>>; /** * Event handler that triggers when a document is created in Firestore. @@ -327,11 +309,9 @@ export function onDocumentCreatedWithAuthContext( export function onDocumentCreatedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext> + event: FirestoreEvent> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext> -> { +): CloudFunction>> { return onOperation(createdEventWithAuthContextType, documentOrOpts, handler); } @@ -385,14 +365,9 @@ export function onDocumentUpdated( export function onDocumentUpdatedWithAuthContext( document: Document, handler: ( - event: FirestoreEventWithAuthContext< - Change | undefined, - ParamsOf - > + event: FirestoreEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext | undefined, ParamsOf> ->; +): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is updated in Firestore. * This trigger also provides the authentication context of the principal who triggered the event. @@ -403,14 +378,9 @@ export function onDocumentUpdatedWithAuthContext( export function onDocumentUpdatedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext< - Change | undefined, - ParamsOf - > + event: FirestoreEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext | undefined, ParamsOf> ->; +): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is updated in Firestore. @@ -421,19 +391,10 @@ export function onDocumentUpdatedWithAuthContext( export function onDocumentUpdatedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext< - Change | undefined, - ParamsOf - > + event: FirestoreEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext | undefined, ParamsOf> -> { - return onChangedWithAuthContextOperation( - updatedEventWithAuthContextType, - documentOrOpts, - handler - ); +): CloudFunction | undefined, ParamsOf>> { + return onChangedOperation(updatedEventWithAuthContextType, documentOrOpts, handler); } /** @@ -487,11 +448,9 @@ export function onDocumentDeleted( export function onDocumentDeletedWithAuthContext( document: Document, handler: ( - event: FirestoreEventWithAuthContext> + event: FirestoreEvent> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext> ->; +): CloudFunction>>; /** * Event handler that triggers when a document is deleted in Firestore. @@ -503,11 +462,9 @@ export function onDocumentDeletedWithAuthContext( export function onDocumentDeletedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext> + event: FirestoreEvent> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext> ->; +): CloudFunction>>; /** * Event handler that triggers when a document is deleted in Firestore. @@ -518,11 +475,9 @@ export function onDocumentDeletedWithAuthContext( export function onDocumentDeletedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEventWithAuthContext> + event: FirestoreEvent> ) => any | Promise -): CloudFunction< - FirestoreEventWithAuthContext> -> { +): CloudFunction>> { return onOperation(deletedEventWithAuthContextType, documentOrOpts, handler); } @@ -613,9 +568,7 @@ export function makeFirestoreEvent( eventType: string, event: RawFirestoreEvent, params: Params -): - | FirestoreEventWithAuthContext - | FirestoreEvent { +): FirestoreEvent { const data = event.data ? eventType === createdEventType ? createSnapshot(event) @@ -625,20 +578,11 @@ export function makeFirestoreEvent( ...event, params, data, + authType: event.authtype as AuthType, + authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; - - if (event.authtype) { - const eventWithAuthContext = { - ...firestoreEvent, - authType: event.authtype as AuthType, - authId: event.authid, - }; - delete (eventWithAuthContext as any).authtype; - delete (eventWithAuthContext as any).authid; - return eventWithAuthContext; - } return firestoreEvent; } @@ -654,34 +598,11 @@ export function makeChangedFirestoreEvent( ...event, params, data, - }; - delete (firestoreEvent as any).datacontenttype; - delete (firestoreEvent as any).dataschema; - return firestoreEvent; -} - -/** @internal */ -export function makeChangedFirestoreEventWithAuthContext( - event: RawFirestoreEvent, - params: Params -): FirestoreEventWithAuthContext | undefined, Params> { - const data = event.data - ? Change.fromObjects(createBeforeSnapshot(event), createSnapshot(event)) - : undefined; - const firestoreEvent: FirestoreEventWithAuthContext< - Change | undefined, - Params - > = { - ...event, - params, - data, authType: event.authtype as AuthType, authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; - delete (firestoreEvent as any).authtype; - delete (firestoreEvent as any).authid; return firestoreEvent; } @@ -780,31 +701,3 @@ export function onChangedOperation( return func; } - -/** @internal */ -export function onChangedWithAuthContextOperation( - eventType: string, - documentOrOpts: Document | DocumentOptions, - handler: ( - event: FirestoreEventWithAuthContext, ParamsOf> - ) => any | Promise -): CloudFunction, ParamsOf>> { - const { document, database, namespace, opts } = getOpts(documentOrOpts); - - // wrap the handler - const func = (raw: CloudEvent) => { - const event = raw as RawFirestoreEvent; - const documentPattern = new PathPattern( - typeof document === "string" ? document : document.value() - ); - const params = makeParams(event.document, documentPattern) as unknown as ParamsOf; - const firestoreEvent = makeChangedFirestoreEventWithAuthContext(event, params); - return wrapTraceContext(withInit(handler))(firestoreEvent); - }; - - func.run = handler; - - func.__endpoint = makeEndpoint(eventType, opts, document, database, namespace); - - return func; -} From 3902b80e70d53f6f1ebd33852ed67aa222409fc8 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Wed, 3 Apr 2024 14:57:57 -0700 Subject: [PATCH 11/12] Ugly type safety (#1548) * Ugly typesafety * Formatter * consolidate make firestore event fns and simplify typings --------- Co-authored-by: Brian Li --- spec/v2/providers/firestore.spec.ts | 40 +++++++- src/v2/providers/firestore.ts | 147 ++++++++++++++++++---------- 2 files changed, 135 insertions(+), 52 deletions(-) diff --git a/spec/v2/providers/firestore.spec.ts b/spec/v2/providers/firestore.spec.ts index 77ed0aa1d..24a10e4a2 100644 --- a/spec/v2/providers/firestore.spec.ts +++ b/spec/v2/providers/firestore.spec.ts @@ -40,8 +40,6 @@ const eventBase = { datacontenttype: "application/protobuf", dataschema: "https://github.com/googleapis/google-cloudevents/blob/main/proto/google/events/cloud/firestore/v1/data.proto", - authtype: "unknown", - authid: "1234", id: "379ad868-5ef9-4c84-a8ba-f75f1b056663", source: "projects/my-project/databases/my-db/documents/d", subject: "documents/foo/fGRodw71mHutZ4wGDuT8", @@ -86,6 +84,15 @@ function makeEvent(data?: any): firestore.RawFirestoreEvent { } as firestore.RawFirestoreEvent; } +function makeAuthEvent(data?: any): firestore.RawFirestoreAuthEvent { + return { + ...eventBase, + data, + authid: "userId", + authtype: "unknown", + } as firestore.RawFirestoreAuthEvent; +} + const createdData = { value: { fields: { @@ -910,6 +917,26 @@ describe("firestore", () => { expect(event.data.data()).to.deep.eq({ hello: "delete world" }); }); + + it("should make event from a created event with auth context", () => { + const event = firestore.makeFirestoreEvent( + firestore.createdEventWithAuthContextType, + makeAuthEvent(makeEncodedProtobuf(createdProto)), + firestore.makeParams("foo/fGRodw71mHutZ4wGDuT8", new PathPattern("foo/{bar}")) + ); + + expect(event.data.data()).to.deep.eq({ hello: "create world" }); + }); + + it("should include auth fields if provided in raw event", () => { + const event = firestore.makeFirestoreEvent( + firestore.createdEventWithAuthContextType, + makeAuthEvent(makeEncodedProtobuf(createdProto)), + firestore.makeParams("foo/fGRodw71mHutZ4wGDuT8", new PathPattern("foo/{bar}")) + ); + + expect(event).to.include({ authId: "userId", authType: "unknown" }); + }); }); describe("makeChangedFirestoreEvent", () => { @@ -943,6 +970,15 @@ describe("firestore", () => { }); }); + it("should include auth fields if provided in raw event", () => { + const event = firestore.makeChangedFirestoreEvent( + makeAuthEvent(makeEncodedProtobuf(writtenProto)), + firestore.makeParams("foo/fGRodw71mHutZ4wGDuT8", new PathPattern("foo/{bar}")) + ); + + expect(event).to.include({ authId: "userId", authType: "unknown" }); + }); + describe("makeEndpoint", () => { it("should make an endpoint with a document path pattern", () => { const expectedEp = makeExpectedEp( diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index 2afcfc332..039125108 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -93,7 +93,11 @@ export interface RawFirestoreEvent extends CloudEvent> extends Clou namespace: string; /** The document path */ document: string; - /** The type of principal that triggered the event */ - authType?: AuthType; - /** The unique identifier for the principal */ - authId?: string; /** * An object containing the values of the path patterns. * Only named capture groups will be populated - {key}, {key=*}, {key=**} @@ -136,6 +136,14 @@ export interface FirestoreEvent> extends Clou params: Params; } +export interface FirestoreAuthEvent> + extends FirestoreEvent { + /** The type of principal that triggered the event */ + authType: AuthType; + /** The unique identifier for the principal */ + authId?: string; +} + /** DocumentOptions extend EventHandlerOptions with provided document and optional database and namespace. */ export interface DocumentOptions extends EventHandlerOptions { /** The document path */ @@ -197,9 +205,9 @@ export function onDocumentWritten( export function onDocumentWrittenWithAuthContext( document: Document, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. @@ -211,9 +219,9 @@ export function onDocumentWrittenWithAuthContext( export function onDocumentWrittenWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is created, updated, or deleted in Firestore. @@ -223,12 +231,19 @@ export function onDocumentWrittenWithAuthContext( * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs. */ export function onDocumentWrittenWithAuthContext( - documentorOpts: Document | DocumentOptions, + documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>> { - return onChangedOperation(writtenEventWithAuthContextType, documentorOpts, handler); +): CloudFunction | undefined, ParamsOf>> { + // const fn = ( + // event: FirestoreEvent | undefined, ParamsOf> & { + // foo: string; + // } + // ): any => { + // return event; + // }; + return onChangedOperation(writtenEventWithAuthContextType, documentOrOpts, handler); } /** @@ -282,9 +297,9 @@ export function onDocumentCreated( export function onDocumentCreatedWithAuthContext( document: Document, handler: ( - event: FirestoreEvent> + event: FirestoreAuthEvent> ) => any | Promise -): CloudFunction>>; +): CloudFunction>>; /** * Event handler that triggers when a document is created in Firestore. @@ -296,9 +311,9 @@ export function onDocumentCreatedWithAuthContext( export function onDocumentCreatedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreAuthEvent> ) => any | Promise -): CloudFunction>>; +): CloudFunction>>; /** * Event handler that triggers when a document is created in Firestore. @@ -309,9 +324,9 @@ export function onDocumentCreatedWithAuthContext( export function onDocumentCreatedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreAuthEvent> ) => any | Promise -): CloudFunction>> { +): CloudFunction>> { return onOperation(createdEventWithAuthContextType, documentOrOpts, handler); } @@ -365,9 +380,10 @@ export function onDocumentUpdated( export function onDocumentUpdatedWithAuthContext( document: Document, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction | undefined, ParamsOf>>; + /** * Event handler that triggers when a document is updated in Firestore. * This trigger also provides the authentication context of the principal who triggered the event. @@ -378,9 +394,9 @@ export function onDocumentUpdatedWithAuthContext( export function onDocumentUpdatedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>>; +): CloudFunction | undefined, ParamsOf>>; /** * Event handler that triggers when a document is updated in Firestore. @@ -391,9 +407,11 @@ export function onDocumentUpdatedWithAuthContext( export function onDocumentUpdatedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent | undefined, ParamsOf> + event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise -): CloudFunction | undefined, ParamsOf>> { +): CloudFunction< + FirestoreAuthEvent | undefined, ParamsOf> +> { return onChangedOperation(updatedEventWithAuthContextType, documentOrOpts, handler); } @@ -448,9 +466,9 @@ export function onDocumentDeleted( export function onDocumentDeletedWithAuthContext( document: Document, handler: ( - event: FirestoreEvent> + event: FirestoreAuthEvent> ) => any | Promise -): CloudFunction>>; +): CloudFunction>>; /** * Event handler that triggers when a document is deleted in Firestore. @@ -462,9 +480,9 @@ export function onDocumentDeletedWithAuthContext( export function onDocumentDeletedWithAuthContext( opts: DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreAuthEvent> ) => any | Promise -): CloudFunction>>; +): CloudFunction>>; /** * Event handler that triggers when a document is deleted in Firestore. @@ -475,9 +493,9 @@ export function onDocumentDeletedWithAuthContext( export function onDocumentDeletedWithAuthContext( documentOrOpts: Document | DocumentOptions, handler: ( - event: FirestoreEvent> + event: FirestoreAuthEvent> ) => any | Promise -): CloudFunction>> { +): CloudFunction>> { return onOperation(deletedEventWithAuthContextType, documentOrOpts, handler); } @@ -566,11 +584,13 @@ export function makeParams(document: string, documentPattern: PathPattern) { /** @internal */ export function makeFirestoreEvent( eventType: string, - event: RawFirestoreEvent, + event: RawFirestoreEvent | RawFirestoreAuthEvent, params: Params -): FirestoreEvent { +): + | FirestoreEvent + | FirestoreAuthEvent { const data = event.data - ? eventType === createdEventType + ? eventType === createdEventType || eventType === createdEventWithAuthContextType ? createSnapshot(event) : createBeforeSnapshot(event) : undefined; @@ -578,19 +598,32 @@ export function makeFirestoreEvent( ...event, params, data, - authType: event.authtype as AuthType, - authId: event.authid, }; + delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; + + if ("authtype" in event) { + const eventWithAuth = { + ...firestoreEvent, + authType: event.authtype, + authId: event.authid, + }; + delete (eventWithAuth as any).authtype; + delete (eventWithAuth as any).authid; + return eventWithAuth; + } + return firestoreEvent; } /** @internal */ export function makeChangedFirestoreEvent( - event: RawFirestoreEvent, + event: RawFirestoreEvent | RawFirestoreAuthEvent, params: Params -): FirestoreEvent | undefined, Params> { +): + | FirestoreEvent | undefined, Params> + | FirestoreAuthEvent | undefined, Params> { const data = event.data ? Change.fromObjects(createBeforeSnapshot(event), createSnapshot(event)) : undefined; @@ -598,11 +631,21 @@ export function makeChangedFirestoreEvent( ...event, params, data, - authType: event.authtype as AuthType, - authId: event.authid, }; delete (firestoreEvent as any).datacontenttype; delete (firestoreEvent as any).dataschema; + + if ("authtype" in event) { + const eventWithAuth = { + ...firestoreEvent, + authType: event.authtype, + authId: event.authid, + }; + delete (eventWithAuth as any).authtype; + delete (eventWithAuth as any).authid; + return eventWithAuth; + } + return firestoreEvent; } @@ -649,16 +692,19 @@ export function makeEndpoint( } /** @internal */ -export function onOperation( +export function onOperation< + Document extends string, + Event extends FirestoreEvent> +>( eventType: string, documentOrOpts: Document | DocumentOptions, - handler: (event: FirestoreEvent>) => any | Promise -): CloudFunction>> { + handler: (event: Event) => any | Promise +): CloudFunction { const { document, database, namespace, opts } = getOpts(documentOrOpts); // wrap the handler const func = (raw: CloudEvent) => { - const event = raw as RawFirestoreEvent; + const event = raw as RawFirestoreEvent | RawFirestoreAuthEvent; const documentPattern = new PathPattern( typeof document === "string" ? document : document.value() ); @@ -675,18 +721,19 @@ export function onOperation( } /** @internal */ -export function onChangedOperation( +export function onChangedOperation< + Document extends string, + Event extends FirestoreEvent, ParamsOf> +>( eventType: string, documentOrOpts: Document | DocumentOptions, - handler: ( - event: FirestoreEvent, ParamsOf> - ) => any | Promise -): CloudFunction, ParamsOf>> { + handler: (event: Event) => any | Promise +): CloudFunction { const { document, database, namespace, opts } = getOpts(documentOrOpts); // wrap the handler const func = (raw: CloudEvent) => { - const event = raw as RawFirestoreEvent; + const event = raw as RawFirestoreEvent | RawFirestoreAuthEvent; const documentPattern = new PathPattern( typeof document === "string" ? document : document.value() ); From 78366011e1892133146bcea0c6429b26073f2c6c Mon Sep 17 00:00:00 2001 From: Brian Li Date: Wed, 3 Apr 2024 18:22:09 -0400 Subject: [PATCH 12/12] add oninit tests --- spec/v2/providers/firestore.spec.ts | 68 +++++++++++++++++++++++++++++ src/v2/providers/firestore.ts | 7 --- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/spec/v2/providers/firestore.spec.ts b/spec/v2/providers/firestore.spec.ts index 24a10e4a2..e5406bdb3 100644 --- a/spec/v2/providers/firestore.spec.ts +++ b/spec/v2/providers/firestore.spec.ts @@ -565,6 +565,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentWrittenWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("onDocumentCreatedWithAuthContext", () => { @@ -612,6 +629,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentCreatedWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("onDocumentUpdatedWithAuthContext", () => { @@ -659,6 +693,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentUpdatedWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("onDocumentDeletedWithAuthContext", () => { @@ -706,6 +757,23 @@ describe("firestore", () => { expect(func.run(true as any)).to.eq(2); expect(func.__endpoint).to.deep.eq(expectedEp); }); + + it("calls init function", async () => { + const event: firestore.RawFirestoreEvent = { + ...eventBase, + datacontenttype: "application/json", + data: { + oldValue: null, + value: null, + }, + }; + + let hello; + onInit(() => (hello = "world")); + expect(hello).to.be.undefined; + await firestore.onDocumentDeletedWithAuthContext("path", () => null)(event); + expect(hello).to.equal("world"); + }); }); describe("getOpts", () => { diff --git a/src/v2/providers/firestore.ts b/src/v2/providers/firestore.ts index 039125108..1d8b823a1 100644 --- a/src/v2/providers/firestore.ts +++ b/src/v2/providers/firestore.ts @@ -236,13 +236,6 @@ export function onDocumentWrittenWithAuthContext( event: FirestoreAuthEvent | undefined, ParamsOf> ) => any | Promise ): CloudFunction | undefined, ParamsOf>> { - // const fn = ( - // event: FirestoreEvent | undefined, ParamsOf> & { - // foo: string; - // } - // ): any => { - // return event; - // }; return onChangedOperation(writtenEventWithAuthContextType, documentOrOpts, handler); }