diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..3a7e12219b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- Fixes issue with filtering on a specific storage bucket using functions in the emulator (#3893) diff --git a/scripts/integration-helpers/framework.ts b/scripts/integration-helpers/framework.ts index 82069f06b80..6afdda54c12 100644 --- a/scripts/integration-helpers/framework.ts +++ b/scripts/integration-helpers/framework.ts @@ -14,6 +14,14 @@ const STORAGE_FUNCTION_V2_ARCHIVED_LOG = "========== STORAGE V2 FUNCTION ARCHIVE const STORAGE_FUNCTION_V2_DELETED_LOG = "========== STORAGE V2 FUNCTION DELETED =========="; const STORAGE_FUNCTION_V2_FINALIZED_LOG = "========== STORAGE V2 FUNCTION FINALIZED =========="; const STORAGE_FUNCTION_V2_METADATA_LOG = "========== STORAGE V2 FUNCTION METADATA =========="; +const STORAGE_BUCKET_FUNCTION_V2_ARCHIVED_LOG = + "========== STORAGE BUCKET V2 FUNCTION ARCHIVED =========="; +const STORAGE_BUCKET_FUNCTION_V2_DELETED_LOG = + "========== STORAGE BUCKET V2 FUNCTION DELETED =========="; +const STORAGE_BUCKET_FUNCTION_V2_FINALIZED_LOG = + "========== STORAGE BUCKET V2 FUNCTION FINALIZED =========="; +const STORAGE_BUCKET_FUNCTION_V2_METADATA_LOG = + "========== STORAGE BUCKET V2 FUNCTION METADATA =========="; /* Functions V1 */ const RTDB_FUNCTION_LOG = "========== RTDB FUNCTION =========="; const FIRESTORE_FUNCTION_LOG = "========== FIRESTORE FUNCTION =========="; @@ -23,6 +31,13 @@ const STORAGE_FUNCTION_ARCHIVED_LOG = "========== STORAGE FUNCTION ARCHIVED ==== const STORAGE_FUNCTION_DELETED_LOG = "========== STORAGE FUNCTION DELETED =========="; const STORAGE_FUNCTION_FINALIZED_LOG = "========== STORAGE FUNCTION FINALIZED =========="; const STORAGE_FUNCTION_METADATA_LOG = "========== STORAGE FUNCTION METADATA =========="; +const STORAGE_BUCKET_FUNCTION_ARCHIVED_LOG = + "========== STORAGE BUCKET FUNCTION ARCHIVED =========="; +const STORAGE_BUCKET_FUNCTION_DELETED_LOG = "========== STORAGE BUCKET FUNCTION DELETED =========="; +const STORAGE_BUCKET_FUNCTION_FINALIZED_LOG = + "========== STORAGE BUCKET FUNCTION FINALIZED =========="; +const STORAGE_BUCKET_FUNCTION_METADATA_LOG = + "========== STORAGE BUCKET FUNCTION METADATA =========="; const ALL_EMULATORS_STARTED_LOG = "All emulators ready"; interface ConnectionInfo { @@ -65,6 +80,10 @@ export class TriggerEndToEndTest { storageDeletedTriggerCount = 0; storageFinalizedTriggerCount = 0; storageMetadataTriggerCount = 0; + storageBucketArchivedTriggerCount = 0; + storageBucketDeletedTriggerCount = 0; + storageBucketFinalizedTriggerCount = 0; + storageBucketMetadataTriggerCount = 0; /* Functions V2 */ pubsubV2TriggerCount = 0; @@ -72,6 +91,10 @@ export class TriggerEndToEndTest { storageV2DeletedTriggerCount = 0; storageV2FinalizedTriggerCount = 0; storageV2MetadataTriggerCount = 0; + storageBucketV2ArchivedTriggerCount = 0; + storageBucketV2DeletedTriggerCount = 0; + storageBucketV2FinalizedTriggerCount = 0; + storageBucketV2MetadataTriggerCount = 0; rtdbFromFirestore = false; firestoreFromRtdb = false; @@ -90,6 +113,33 @@ export class TriggerEndToEndTest { } } + resetCounts(): void { + /* Functions V1 */ + this.firestoreTriggerCount = 0; + this.rtdbTriggerCount = 0; + this.pubsubTriggerCount = 0; + this.authTriggerCount = 0; + this.storageArchivedTriggerCount = 0; + this.storageDeletedTriggerCount = 0; + this.storageFinalizedTriggerCount = 0; + this.storageMetadataTriggerCount = 0; + this.storageBucketArchivedTriggerCount = 0; + this.storageBucketDeletedTriggerCount = 0; + this.storageBucketFinalizedTriggerCount = 0; + this.storageBucketMetadataTriggerCount = 0; + + /* Functions V2 */ + this.pubsubV2TriggerCount = 0; + this.storageV2ArchivedTriggerCount = 0; + this.storageV2DeletedTriggerCount = 0; + this.storageV2FinalizedTriggerCount = 0; + this.storageV2MetadataTriggerCount = 0; + this.storageBucketV2ArchivedTriggerCount = 0; + this.storageBucketV2DeletedTriggerCount = 0; + this.storageBucketV2FinalizedTriggerCount = 0; + this.storageBucketV2MetadataTriggerCount = 0; + } + /* * Check that all directions of database <-> functions <-> firestore * worked. @@ -138,6 +188,18 @@ export class TriggerEndToEndTest { if (data.includes(STORAGE_FUNCTION_METADATA_LOG)) { this.storageMetadataTriggerCount++; } + if (data.includes(STORAGE_BUCKET_FUNCTION_ARCHIVED_LOG)) { + this.storageBucketArchivedTriggerCount++; + } + if (data.includes(STORAGE_BUCKET_FUNCTION_DELETED_LOG)) { + this.storageBucketDeletedTriggerCount++; + } + if (data.includes(STORAGE_BUCKET_FUNCTION_FINALIZED_LOG)) { + this.storageBucketFinalizedTriggerCount++; + } + if (data.includes(STORAGE_BUCKET_FUNCTION_METADATA_LOG)) { + this.storageBucketMetadataTriggerCount++; + } /* Functions V2 */ if (data.includes(PUBSUB_FUNCTION_V2_LOG)) { this.pubsubV2TriggerCount++; @@ -154,6 +216,18 @@ export class TriggerEndToEndTest { if (data.includes(STORAGE_FUNCTION_V2_METADATA_LOG)) { this.storageV2MetadataTriggerCount++; } + if (data.includes(STORAGE_BUCKET_FUNCTION_V2_ARCHIVED_LOG)) { + this.storageBucketV2ArchivedTriggerCount++; + } + if (data.includes(STORAGE_BUCKET_FUNCTION_V2_DELETED_LOG)) { + this.storageBucketV2DeletedTriggerCount++; + } + if (data.includes(STORAGE_BUCKET_FUNCTION_V2_FINALIZED_LOG)) { + this.storageBucketV2FinalizedTriggerCount++; + } + if (data.includes(STORAGE_BUCKET_FUNCTION_V2_METADATA_LOG)) { + this.storageBucketV2MetadataTriggerCount++; + } }); this.cliProcess = cli; @@ -209,12 +283,20 @@ export class TriggerEndToEndTest { return this.invokeHttpFunction("writeToScheduledPubsub"); } - writeToStorage(): Promise { - return this.invokeHttpFunction("writeToStorage"); + writeToDefaultStorage(): Promise { + return this.invokeHttpFunction("writeToDefaultStorage"); + } + + writeToSpecificStorageBucket(): Promise { + return this.invokeHttpFunction("writeToSpecificStorageBucket"); + } + + updateDeleteFromDefaultStorage(): Promise { + return this.invokeHttpFunction("updateDeleteFromDefaultStorage"); } - updateDeleteFromStorage(): Promise { - return this.invokeHttpFunction("updateDeleteFromStorage"); + updateDeleteFromSpecificStorageBucket(): Promise { + return this.invokeHttpFunction("updateDeleteFromSpecificStorageBucket"); } waitForCondition( diff --git a/scripts/triggers-end-to-end-tests/functions/index.js b/scripts/triggers-end-to-end-tests/functions/index.js index bb18ff9a3c4..9778e546674 100644 --- a/scripts/triggers-end-to-end-tests/functions/index.js +++ b/scripts/triggers-end-to-end-tests/functions/index.js @@ -23,12 +23,27 @@ const STORAGE_FUNCTION_ARCHIVED_LOG = "========== STORAGE FUNCTION ARCHIVED ==== const STORAGE_FUNCTION_DELETED_LOG = "========== STORAGE FUNCTION DELETED =========="; const STORAGE_FUNCTION_FINALIZED_LOG = "========== STORAGE FUNCTION FINALIZED =========="; const STORAGE_FUNCTION_METADATA_LOG = "========== STORAGE FUNCTION METADATA =========="; +const STORAGE_BUCKET_FUNCTION_ARCHIVED_LOG = + "========== STORAGE BUCKET FUNCTION ARCHIVED =========="; +const STORAGE_BUCKET_FUNCTION_DELETED_LOG = "========== STORAGE BUCKET FUNCTION DELETED =========="; +const STORAGE_BUCKET_FUNCTION_FINALIZED_LOG = + "========== STORAGE BUCKET FUNCTION FINALIZED =========="; +const STORAGE_BUCKET_FUNCTION_METADATA_LOG = + "========== STORAGE BUCKET FUNCTION METADATA =========="; /* Functions V2 */ const PUBSUB_FUNCTION_V2_LOG = "========== PUBSUB V2 FUNCTION =========="; const STORAGE_FUNCTION_V2_ARCHIVED_LOG = "========== STORAGE V2 FUNCTION ARCHIVED =========="; const STORAGE_FUNCTION_V2_DELETED_LOG = "========== STORAGE V2 FUNCTION DELETED =========="; const STORAGE_FUNCTION_V2_FINALIZED_LOG = "========== STORAGE V2 FUNCTION FINALIZED =========="; const STORAGE_FUNCTION_V2_METADATA_LOG = "========== STORAGE V2 FUNCTION METADATA =========="; +const STORAGE_BUCKET_FUNCTION_V2_ARCHIVED_LOG = + "========== STORAGE BUCKET V2 FUNCTION ARCHIVED =========="; +const STORAGE_BUCKET_FUNCTION_V2_DELETED_LOG = + "========== STORAGE BUCKET V2 FUNCTION DELETED =========="; +const STORAGE_BUCKET_FUNCTION_V2_FINALIZED_LOG = + "========== STORAGE BUCKET V2 FUNCTION FINALIZED =========="; +const STORAGE_BUCKET_FUNCTION_V2_METADATA_LOG = + "========== STORAGE BUCKET V2 FUNCTION METADATA =========="; /* * We install onWrite triggers for START_DOCUMENT_NAME in both the firestore and @@ -99,13 +114,19 @@ exports.writeToAuth = functions.https.onRequest(async (req, res) => { res.json({ created: "ok" }); }); -exports.writeToStorage = functions.https.onRequest(async (req, res) => { +exports.writeToDefaultStorage = functions.https.onRequest(async (req, res) => { await admin.storage().bucket().file(STORAGE_FILE_NAME).save("hello world!"); - console.log("Wrote to Storage bucket"); + console.log("Wrote to default Storage bucket"); res.json({ created: "ok" }); }); -exports.updateDeleteFromStorage = functions.https.onRequest(async (req, res) => { +exports.writeToSpecificStorageBucket = functions.https.onRequest(async (req, res) => { + await admin.storage().bucket("test-bucket").file(STORAGE_FILE_NAME).save("hello world!"); + console.log("Wrote to a specific Storage bucket"); + res.json({ created: "ok" }); +}); + +exports.updateDeleteFromDefaultStorage = functions.https.onRequest(async (req, res) => { await admin.storage().bucket().file(STORAGE_FILE_NAME).save("something new!"); console.log("Wrote to Storage bucket"); await admin.storage().bucket().file(STORAGE_FILE_NAME).delete(); @@ -113,6 +134,14 @@ exports.updateDeleteFromStorage = functions.https.onRequest(async (req, res) => res.json({ done: "ok" }); }); +exports.updateDeleteFromSpecificStorageBucket = functions.https.onRequest(async (req, res) => { + await admin.storage().bucket("test-bucket").file(STORAGE_FILE_NAME).save("something new!"); + console.log("Wrote to a specific Storage bucket"); + await admin.storage().bucket("test-bucket").file(STORAGE_FILE_NAME).delete(); + console.log("Deleted from a specific Storage bucket"); + res.json({ done: "ok" }); +}); + exports.firestoreReaction = functions.firestore .document(START_DOCUMENT_NAME) .onWrite(async (/* change, ctx */) => { @@ -175,29 +204,41 @@ exports.authReaction = functions.auth.user().onCreate((user, ctx) => { return true; }); -exports.storageArchiveReaction = functions.storage.object().onArchive((object, context) => { - console.log(STORAGE_FUNCTION_ARCHIVED_LOG); - console.log("Object", JSON.stringify(object)); - return true; -}); +exports.storageArchiveReaction = functions.storage + .bucket() + .object() + .onArchive((object, context) => { + console.log(STORAGE_FUNCTION_ARCHIVED_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); -exports.storageDeleteReaction = functions.storage.object().onDelete((object, context) => { - console.log(STORAGE_FUNCTION_DELETED_LOG); - console.log("Object", JSON.stringify(object)); - return true; -}); +exports.storageDeleteReaction = functions.storage + .bucket() + .object() + .onDelete((object, context) => { + console.log(STORAGE_FUNCTION_DELETED_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); -exports.storageFinalizeReaction = functions.storage.object().onFinalize((object, context) => { - console.log(STORAGE_FUNCTION_FINALIZED_LOG); - console.log("Object", JSON.stringify(object)); - return true; -}); +exports.storageFinalizeReaction = functions.storage + .bucket() + .object() + .onFinalize((object, context) => { + console.log(STORAGE_FUNCTION_FINALIZED_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); -exports.storageMetadataReaction = functions.storage.object().onMetadataUpdate((object, context) => { - console.log(STORAGE_FUNCTION_METADATA_LOG); - console.log("Object", JSON.stringify(object)); - return true; -}); +exports.storageMetadataReaction = functions.storage + .bucket() + .object() + .onMetadataUpdate((object, context) => { + console.log(STORAGE_FUNCTION_METADATA_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); exports.storagev2archivedreaction = functionsV2.storage.onObjectArchived((cloudevent) => { console.log(STORAGE_FUNCTION_V2_ARCHIVED_LOG); @@ -222,3 +263,75 @@ exports.storagev2metadatareaction = functionsV2.storage.onObjectMetadataUpdated( console.log("Object", JSON.stringify(cloudevent.data)); return true; }); + +exports.storageBucketArchiveReaction = functions.storage + .bucket("test-bucket") + .object() + .onArchive((object, context) => { + console.log(STORAGE_BUCKET_FUNCTION_ARCHIVED_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); + +exports.storageBucketDeleteReaction = functions.storage + .bucket("test-bucket") + .object() + .onDelete((object, context) => { + console.log(STORAGE_BUCKET_FUNCTION_DELETED_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); + +exports.storageBucketFinalizeReaction = functions.storage + .bucket("test-bucket") + .object() + .onFinalize((object, context) => { + console.log(STORAGE_BUCKET_FUNCTION_FINALIZED_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); + +exports.storageBucketMetadataReaction = functions.storage + .bucket("test-bucket") + .object() + .onMetadataUpdate((object, context) => { + console.log(STORAGE_BUCKET_FUNCTION_METADATA_LOG); + console.log("Object", JSON.stringify(object)); + return true; + }); + +exports.storagebucketv2archivedreaction = functionsV2.storage.onObjectArchived( + "test-bucket", + (cloudevent) => { + console.log(STORAGE_BUCKET_FUNCTION_V2_ARCHIVED_LOG); + console.log("Object", JSON.stringify(cloudevent.data)); + return true; + } +); + +exports.storagebucketv2deletedreaction = functionsV2.storage.onObjectDeleted( + "test-bucket", + (cloudevent) => { + console.log(STORAGE_BUCKET_FUNCTION_V2_DELETED_LOG); + console.log("Object", JSON.stringify(cloudevent.data)); + return true; + } +); + +exports.storagebucketv2finalizedreaction = functionsV2.storage.onObjectFinalized( + "test-bucket", + (cloudevent) => { + console.log(STORAGE_BUCKET_FUNCTION_V2_FINALIZED_LOG); + console.log("Object", JSON.stringify(cloudevent.data)); + return true; + } +); + +exports.storagebucketv2metadatareaction = functionsV2.storage.onObjectMetadataUpdated( + "test-bucket", + (cloudevent) => { + console.log(STORAGE_BUCKET_FUNCTION_V2_METADATA_LOG); + console.log("Object", JSON.stringify(cloudevent.data)); + return true; + } +); diff --git a/scripts/triggers-end-to-end-tests/tests.ts b/scripts/triggers-end-to-end-tests/tests.ts index a5982812efb..8063f98f20f 100755 --- a/scripts/triggers-end-to-end-tests/tests.ts +++ b/scripts/triggers-end-to-end-tests/tests.ts @@ -261,39 +261,114 @@ describe("storage emulator function triggers", () => { await test.stopEmulators(); }); - it("should write to the storage emulator", async function (this) { + it("should write to the default bucket of storage emulator", async function (this) { this.timeout(EMULATOR_TEST_TIMEOUT); - const response = await test.writeToStorage(); + const response = await test.writeToDefaultStorage(); expect(response.status).to.equal(200); await new Promise((resolve) => setTimeout(resolve, EMULATORS_WRITE_DELAY_MS)); }); it("should have triggered cloud functions", () => { - // on object create two events fire (finalize & metadata update) + /* on object create two events fire (finalize & metadata update) */ + // default bucket expect(test.storageFinalizedTriggerCount).to.equal(1); expect(test.storageMetadataTriggerCount).to.equal(1); expect(test.storageV2FinalizedTriggerCount).to.equal(1); expect(test.storageV2MetadataTriggerCount).to.equal(1); + expect(test.storageDeletedTriggerCount).to.equal(0); + expect(test.storageV2DeletedTriggerCount).to.equal(0); + // specific bucket + expect(test.storageBucketFinalizedTriggerCount).to.equal(0); + expect(test.storageBucketMetadataTriggerCount).to.equal(0); + expect(test.storageBucketV2FinalizedTriggerCount).to.equal(0); + expect(test.storageBucketV2MetadataTriggerCount).to.equal(0); + expect(test.storageBucketDeletedTriggerCount).to.equal(0); + expect(test.storageBucketV2DeletedTriggerCount).to.equal(0); + test.resetCounts(); }); - it("should write, update, and delete from the storage emulator", async function (this) { + it("should write to a specific bucket of storage emulator", async function (this) { this.timeout(EMULATOR_TEST_TIMEOUT); - const response = await test.updateDeleteFromStorage(); + const response = await test.writeToSpecificStorageBucket(); expect(response.status).to.equal(200); await new Promise((resolve) => setTimeout(resolve, EMULATORS_WRITE_DELAY_MS)); }); it("should have triggered cloud functions", () => { - // on update two events fire (finalize & metadata update) - expect(test.storageFinalizedTriggerCount).to.equal(2); - expect(test.storageMetadataTriggerCount).to.equal(2); - expect(test.storageV2FinalizedTriggerCount).to.equal(2); - expect(test.storageV2MetadataTriggerCount).to.equal(2); - // on delete one event fires (delete) + /* on object create two events fire (finalize & metadata update) */ + // default bucket + expect(test.storageFinalizedTriggerCount).to.equal(0); + expect(test.storageMetadataTriggerCount).to.equal(0); + expect(test.storageV2FinalizedTriggerCount).to.equal(0); + expect(test.storageV2MetadataTriggerCount).to.equal(0); + expect(test.storageDeletedTriggerCount).to.equal(0); + expect(test.storageV2DeletedTriggerCount).to.equal(0); + // specific bucket + expect(test.storageBucketFinalizedTriggerCount).to.equal(1); + expect(test.storageBucketMetadataTriggerCount).to.equal(1); + expect(test.storageBucketV2FinalizedTriggerCount).to.equal(1); + expect(test.storageBucketV2MetadataTriggerCount).to.equal(1); + expect(test.storageBucketDeletedTriggerCount).to.equal(0); + expect(test.storageBucketV2DeletedTriggerCount).to.equal(0); + test.resetCounts(); + }); + + it("should write, update, and delete from the default bucket of the storage emulator", async function (this) { + this.timeout(EMULATOR_TEST_TIMEOUT); + + const response = await test.updateDeleteFromDefaultStorage(); + expect(response.status).to.equal(200); + await new Promise((resolve) => setTimeout(resolve, EMULATORS_WRITE_DELAY_MS)); + }); + + it("should have triggered cloud functions", () => { + /* on update two events fire (finalize & metadata update) */ + /* on delete one event fires (delete) */ + // default bucket + expect(test.storageFinalizedTriggerCount).to.equal(1); + expect(test.storageMetadataTriggerCount).to.equal(1); + expect(test.storageV2FinalizedTriggerCount).to.equal(1); + expect(test.storageV2MetadataTriggerCount).to.equal(1); expect(test.storageDeletedTriggerCount).to.equal(1); expect(test.storageV2DeletedTriggerCount).to.equal(1); + // specific bucket + expect(test.storageBucketFinalizedTriggerCount).to.equal(0); + expect(test.storageBucketMetadataTriggerCount).to.equal(0); + expect(test.storageBucketV2FinalizedTriggerCount).to.equal(0); + expect(test.storageBucketV2MetadataTriggerCount).to.equal(0); + expect(test.storageBucketDeletedTriggerCount).to.equal(0); + expect(test.storageBucketV2DeletedTriggerCount).to.equal(0); + test.resetCounts(); + }); + + it("should write, update, and delete from a specific bucket of the storage emulator", async function (this) { + this.timeout(EMULATOR_TEST_TIMEOUT); + + const response = await test.updateDeleteFromSpecificStorageBucket(); + expect(response.status).to.equal(200); + await new Promise((resolve) => setTimeout(resolve, EMULATORS_WRITE_DELAY_MS)); + }); + + it("should have triggered cloud functions", () => { + /* on update two events fire (finalize & metadata update) */ + /* on delete one event fires (delete) */ + // default bucket + expect(test.storageFinalizedTriggerCount).to.equal(0); + expect(test.storageMetadataTriggerCount).to.equal(0); + expect(test.storageV2FinalizedTriggerCount).to.equal(0); + expect(test.storageV2MetadataTriggerCount).to.equal(0); + expect(test.storageDeletedTriggerCount).to.equal(0); + expect(test.storageV2DeletedTriggerCount).to.equal(0); + // specific bucket + expect(test.storageBucketFinalizedTriggerCount).to.equal(1); + expect(test.storageBucketMetadataTriggerCount).to.equal(1); + expect(test.storageBucketV2FinalizedTriggerCount).to.equal(1); + expect(test.storageBucketV2MetadataTriggerCount).to.equal(1); + expect(test.storageBucketDeletedTriggerCount).to.equal(1); + expect(test.storageBucketV2DeletedTriggerCount).to.equal(1); + test.resetCounts(); }); }); diff --git a/src/emulator/functionsEmulator.ts b/src/emulator/functionsEmulator.ts index 93a007987ff..ec5fe17941d 100644 --- a/src/emulator/functionsEmulator.ts +++ b/src/emulator/functionsEmulator.ts @@ -281,6 +281,9 @@ export class FunctionsEmulator implements EmulatorInstance { } else { triggerKey = `${this.args.projectId}:${proto.eventType}`; } + if (proto.data.bucket) { + triggerKey += `:${proto.data.bucket}`; + } const triggers = this.multicastTriggers[triggerKey] || []; triggers.forEach((triggerId) => { @@ -706,7 +709,10 @@ export class FunctionsEmulator implements EmulatorInstance { addStorageTrigger(projectId: string, key: string, eventTrigger: EventTrigger): boolean { logger.debug(`addStorageTrigger`, JSON.stringify({ eventTrigger })); - const eventTriggerId = `${projectId}:${eventTrigger.eventType}`; + const bucket = eventTrigger.resource.startsWith("projects/_/buckets/") + ? eventTrigger.resource.split("/")[3] + : eventTrigger.resource; + const eventTriggerId = `${projectId}:${eventTrigger.eventType}:${bucket}`; const triggers = this.multicastTriggers[eventTriggerId] || []; triggers.push(key); this.multicastTriggers[eventTriggerId] = triggers; diff --git a/src/emulator/storage/cloudFunctions.ts b/src/emulator/storage/cloudFunctions.ts index d921da51606..071840362f7 100644 --- a/src/emulator/storage/cloudFunctions.ts +++ b/src/emulator/storage/cloudFunctions.ts @@ -99,7 +99,7 @@ export class StorageCloudFunctions { ): string { const ceAction = STORAGE_V2_ACTION_MAP[action]; if (!ceAction) { - throw new Error("Action is not definied as a CloudEvents action"); + throw new Error("Action is not defined as a CloudEvents action"); } const data = (objectMetadataPayload as unknown) as StorageObjectData; return JSON.stringify({