Conversation
There was a problem hiding this comment.
Code Review
This pull request migrates various Firebase Cloud Functions from v1 to v2 syntax across several example projects. The review feedback highlights a recurring issue where the new v2 event handlers incorrectly destructure arguments; in v2, the trigger data is encapsulated within a single event object's 'data' property. Actionable suggestions were provided to correct the function signatures for Realtime Database, Pub/Sub, Cloud Storage, Firestore, and Remote Config triggers to prevent runtime errors.
| // Note: This is a Realtime Database trigger, *not* Firestore. | ||
| exports.onUserStatusChanged = functions.database.ref('/status/{uid}').onUpdate( | ||
| async (change, context) => { | ||
| exports.onUserStatusChanged = onValueUpdated('/status/{uid}', async ({ change, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the trigger handler receives a single event object. For Realtime Database triggers, the Change object is available in the data property of this event. The current destructuring will result in change and context being undefined, causing the function to fail when accessing change.after or context.params.
| exports.onUserStatusChanged = onValueUpdated('/status/{uid}', async ({ change, context }) => { | |
| exports.onUserStatusChanged = onValueUpdated('/status/{uid}', async ({ data: change, ...context }) => { |
| */ | ||
| // [START trigger] | ||
| exports.helloPubSub = functions.pubsub.topic('topic-name').onPublish((message) => { | ||
| exports.helloPubSub = onMessagePublished('topic-name', ({ message, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Pub/Sub handler receives a single event object. The message data is located at event.data.message. The current destructuring will result in message being undefined.
| exports.helloPubSub = onMessagePublished('topic-name', ({ message, context }) => { | |
| exports.helloPubSub = onMessagePublished('topic-name', ({ data: { message } }) => { |
| * topic as JSON. | ||
| */ | ||
| exports.helloPubSubJson = functions.pubsub.topic('another-topic-name').onPublish((message) => { | ||
| exports.helloPubSubJson = onMessagePublished('another-topic-name', ({ message, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Pub/Sub handler receives a single event object. The message data is located at event.data.message. Additionally, the v2 Message object no longer includes the .json helper property found in v1. You will need to parse the JSON from message.data manually (e.g., JSON.parse(Buffer.from(message.data, 'base64').toString())) in the function body.
| exports.helloPubSubJson = onMessagePublished('another-topic-name', ({ message, context }) => { | |
| exports.helloPubSubJson = onMessagePublished('another-topic-name', ({ data: { message } }) => { |
| * published to the topic. | ||
| */ | ||
| exports.helloPubSubAttributes = functions.pubsub.topic('yet-another-topic-name').onPublish((message) => { | ||
| exports.helloPubSubAttributes = onMessagePublished('yet-another-topic-name', ({ message, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Pub/Sub handler receives a single event object. The message data is located at event.data.message.
| exports.helloPubSubAttributes = onMessagePublished('yet-another-topic-name', ({ message, context }) => { | |
| exports.helloPubSubAttributes = onMessagePublished('yet-another-topic-name', ({ data: { message } }) => { |
| */ | ||
| // [START generateThumbnailTrigger] | ||
| exports.firstGenGenerateThumbnail = functions.storage.object().onFinalize(async (object) => { | ||
| exports.firstGenGenerateThumbnail = onObjectFinalized(async ({ object, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Storage handler receives a single event object. The object metadata is located in the data property of this event.
| exports.firstGenGenerateThumbnail = onObjectFinalized(async ({ object, context }) => { | |
| exports.firstGenGenerateThumbnail = onObjectFinalized(async ({ data: object }) => { |
| exports.makeUppercase = functions.firestore | ||
| .document("/messages/{documentId}") | ||
| .onCreate((snap, context) => { | ||
| exports.makeUppercase = onDocumentCreated("/messages/{documentId}", ({ snapshot: snap, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Firestore handler receives a single event object. For onDocumentCreated, the document snapshot is available in the data property. The current destructuring will cause the function to fail when accessing snap.data() or context.params.
| exports.makeUppercase = onDocumentCreated("/messages/{documentId}", ({ snapshot: snap, context }) => { | |
| exports.makeUppercase = onDocumentCreated("/messages/{documentId}", ({ data: snap, ...context }) => { |
| // uppercase version of the message to /messages/:pushId/uppercase | ||
| exports.makeUppercase = functions.database.ref('/messages/{pushId}/original') | ||
| .onCreate((snapshot, context) => { | ||
| exports.makeUppercase = onValueCreated('/messages/{pushId}/original', ({ snapshot, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Realtime Database handler receives a single event object. The data snapshot is available in the data property. The current destructuring will cause the function to fail when accessing snapshot.val() or context.params.
| exports.makeUppercase = onValueCreated('/messages/{pushId}/original', ({ snapshot, context }) => { | |
| exports.makeUppercase = onValueCreated('/messages/{pushId}/original', ({ data: snapshot, ...context }) => { |
|
|
||
| // [START remote_config_function] | ||
| exports.showConfigDiff = functions.remoteConfig.onUpdate(versionMetadata => { | ||
| exports.showConfigDiff = onConfigUpdated(({ version: versionMetadata, context }) => { |
There was a problem hiding this comment.
In Cloud Functions v2, the Remote Config handler receives a single event object. The version metadata is available in the data property. The current destructuring will result in versionMetadata being undefined.
| exports.showConfigDiff = onConfigUpdated(({ version: versionMetadata, context }) => { | |
| exports.showConfigDiff = onConfigUpdated(({ data: versionMetadata }) => { |
Testing out the new agent-skills. Use this PR to analyse the diff between the v1 code and the agent-updated v2 code.