firebase-functions 7.2.2 → 7.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/lib/common/providers/tasks.js +1 -0
  2. package/lib/common/utilities/path-pattern.js +12 -3
  3. package/lib/esm/common/providers/tasks.mjs +1 -0
  4. package/lib/esm/common/utilities/path-pattern.mjs +11 -3
  5. package/lib/esm/v2/compat.mjs +19 -59
  6. package/lib/esm/v2/index.doc.mjs +1 -1
  7. package/lib/esm/v2/index.mjs +2 -2
  8. package/lib/esm/v2/providers/ai/index.mjs +187 -0
  9. package/lib/esm/v2/providers/ai/types/gemini/v1beta/index.mjs +6 -0
  10. package/lib/esm/v2/providers/ai/types/vertex/v1beta1/index.mjs +6 -0
  11. package/lib/esm/v2/providers/database.mjs +35 -2
  12. package/lib/esm/v2/providers/firestore.mjs +38 -6
  13. package/lib/esm/v2/providers/https.mjs +10 -2
  14. package/lib/esm/v2/providers/pubsub.mjs +42 -2
  15. package/lib/esm/v2/providers/remoteConfig.mjs +18 -1
  16. package/lib/esm/v2/providers/scheduler.mjs +12 -0
  17. package/lib/esm/v2/providers/storage.mjs +24 -1
  18. package/lib/v2/compat.d.ts +14 -12
  19. package/lib/v2/compat.js +19 -58
  20. package/lib/v2/index.d.ts +0 -1
  21. package/lib/v2/index.doc.js +1 -1
  22. package/lib/v2/index.js +2 -2
  23. package/lib/v2/providers/ai/index.d.ts +53 -0
  24. package/lib/v2/providers/ai/index.js +198 -0
  25. package/lib/v2/providers/ai/types/gemini/v1beta/index.d.ts +817 -0
  26. package/lib/v2/providers/ai/types/gemini/v1beta/index.js +8 -0
  27. package/lib/v2/providers/ai/types/vertex/v1beta1/index.d.ts +850 -0
  28. package/lib/v2/providers/ai/types/vertex/v1beta1/index.js +8 -0
  29. package/lib/v2/providers/database.d.ts +61 -4
  30. package/lib/v2/providers/database.js +35 -2
  31. package/lib/v2/providers/firestore.d.ts +127 -0
  32. package/lib/v2/providers/firestore.js +38 -5
  33. package/lib/v2/providers/https.d.ts +2 -2
  34. package/lib/v2/providers/https.js +10 -2
  35. package/lib/v2/providers/pubsub.d.ts +18 -4
  36. package/lib/v2/providers/pubsub.js +42 -2
  37. package/lib/v2/providers/remoteConfig.d.ts +16 -0
  38. package/lib/v2/providers/remoteConfig.js +18 -1
  39. package/lib/v2/providers/scheduler.d.ts +21 -0
  40. package/lib/v2/providers/scheduler.js +12 -0
  41. package/lib/v2/providers/storage.d.ts +127 -0
  42. package/lib/v2/providers/storage.js +24 -1
  43. package/lib/v2/providers/tasks.d.ts +20 -1
  44. package/package.json +1 -1
@@ -47,6 +47,7 @@ function onDispatchHandler(handler) {
47
47
  ...context,
48
48
  data
49
49
  };
50
+ Object.defineProperty(arg, "context", { get: () => context });
50
51
  await handler(arg);
51
52
  }
52
53
  res.status(204).end();
@@ -12,6 +12,14 @@ function trimParam(param) {
12
12
  }
13
13
  return paramNoBraces;
14
14
  }
15
+ /** @internal */
16
+ function tryDecodeURIComponent(uri) {
17
+ try {
18
+ return decodeURIComponent(uri);
19
+ } catch (_e) {
20
+ return uri;
21
+ }
22
+ }
15
23
  /** @hidden */
16
24
  var Segment = class {
17
25
  constructor(value) {
@@ -89,9 +97,9 @@ var PathPattern = class {
89
97
  const remainingSegments = this.segments.length - 1 - segmentNdx;
90
98
  const nextPathNdx = pathSegments.length - remainingSegments;
91
99
  if (segment.name === "single-capture") {
92
- matches[segment.trimmed] = pathSegments[pathNdx];
100
+ matches[segment.trimmed] = tryDecodeURIComponent(pathSegments[pathNdx]);
93
101
  } else if (segment.name === "multi-capture") {
94
- matches[segment.trimmed] = pathSegments.slice(pathNdx, nextPathNdx).join("/");
102
+ matches[segment.trimmed] = tryDecodeURIComponent(pathSegments.slice(pathNdx, nextPathNdx).join("/"));
95
103
  }
96
104
  pathNdx = segment.isMultiSegmentWildcard() ? nextPathNdx : pathNdx + 1;
97
105
  }
@@ -114,4 +122,5 @@ var PathPattern = class {
114
122
 
115
123
  //#endregion
116
124
  exports.PathPattern = PathPattern;
117
- exports.trimParam = trimParam;
125
+ exports.trimParam = trimParam;
126
+ exports.tryDecodeURIComponent = tryDecodeURIComponent;
@@ -47,6 +47,7 @@ function onDispatchHandler(handler) {
47
47
  ...context,
48
48
  data
49
49
  };
50
+ Object.defineProperty(arg, "context", { get: () => context });
50
51
  await handler(arg);
51
52
  }
52
53
  res.status(204).end();
@@ -12,6 +12,14 @@ function trimParam(param) {
12
12
  }
13
13
  return paramNoBraces;
14
14
  }
15
+ /** @internal */
16
+ function tryDecodeURIComponent(uri) {
17
+ try {
18
+ return decodeURIComponent(uri);
19
+ } catch (_e) {
20
+ return uri;
21
+ }
22
+ }
15
23
  /** @hidden */
16
24
  var Segment = class {
17
25
  constructor(value) {
@@ -89,9 +97,9 @@ var PathPattern = class {
89
97
  const remainingSegments = this.segments.length - 1 - segmentNdx;
90
98
  const nextPathNdx = pathSegments.length - remainingSegments;
91
99
  if (segment.name === "single-capture") {
92
- matches[segment.trimmed] = pathSegments[pathNdx];
100
+ matches[segment.trimmed] = tryDecodeURIComponent(pathSegments[pathNdx]);
93
101
  } else if (segment.name === "multi-capture") {
94
- matches[segment.trimmed] = pathSegments.slice(pathNdx, nextPathNdx).join("/");
102
+ matches[segment.trimmed] = tryDecodeURIComponent(pathSegments.slice(pathNdx, nextPathNdx).join("/"));
95
103
  }
96
104
  pathNdx = segment.isMultiSegmentWildcard() ? nextPathNdx : pathNdx + 1;
97
105
  }
@@ -113,4 +121,4 @@ var PathPattern = class {
113
121
  };
114
122
 
115
123
  //#endregion
116
- export { PathPattern, trimParam };
124
+ export { PathPattern, trimParam, tryDecodeURIComponent };
@@ -1,14 +1,13 @@
1
- import { Message } from "./providers/pubsub.mjs";
2
-
3
1
  //#region src/v2/compat.ts
4
2
  const V1_COMPAT_PATCHED = Symbol.for("firebase.functions.v2.compat");
5
3
  /**
6
- * Patches a CloudEvent with V1 compatibility properties (context and message) if it's a supported type (e.g., Pub/Sub).
4
+ * Patches a CloudEvent with V1 compatibility properties via getters.
7
5
  * This function ensures idempotency by using a Symbol to mark already patched events.
8
- * @param event The CloudEvent to potentially patch.
9
- * @returns The patched CloudEvent with V1 compatibility properties, or the original event if not a supported event type or already patched.
6
+ * @param event The CloudEvent to patch.
7
+ * @param getters A map of getters to attach to the event object.
8
+ * @returns The patched CloudEvent with V1 compatibility properties.
10
9
  */
11
- function patchV1Compat(event) {
10
+ function addV1Compat(event, getters) {
12
11
  if (event[V1_COMPAT_PATCHED]) {
13
12
  return event;
14
13
  }
@@ -18,60 +17,21 @@ function patchV1Compat(event) {
18
17
  writable: false,
19
18
  configurable: false
20
19
  });
21
- switch (event.type) {
22
- case "google.cloud.pubsub.topic.v1.messagePublished": {
23
- const pubsubEvent = event;
24
- const pubsubData = pubsubEvent.data;
25
- if (!pubsubData || !pubsubData.message) {
26
- throw new Error("Malformed Pub/Sub event: missing 'message' property.");
27
- }
28
- if (!(pubsubData.message instanceof Message)) {
29
- pubsubData.message = new Message(pubsubData.message);
30
- }
31
- const v2Message = pubsubData.message;
32
- Object.defineProperty(pubsubEvent, "context", {
33
- get: () => {
34
- const service = "pubsub.googleapis.com";
35
- const sourcePrefix = `//${service}/`;
36
- return {
37
- eventId: v2Message.messageId,
38
- timestamp: v2Message.publishTime,
39
- eventType: "google.pubsub.topic.publish",
40
- resource: {
41
- service,
42
- name: event.source?.startsWith(sourcePrefix) ? event.source.substring(sourcePrefix.length) : event.source || ""
43
- },
44
- params: {}
45
- };
46
- },
47
- configurable: true,
48
- enumerable: true
49
- });
50
- Object.defineProperty(pubsubEvent, "message", {
51
- get: () => {
52
- const baseV1Message = {
53
- data: v2Message.data,
54
- messageId: v2Message.messageId,
55
- publishTime: v2Message.publishTime,
56
- attributes: v2Message.attributes,
57
- ...v2Message.orderingKey && { orderingKey: v2Message.orderingKey }
58
- };
59
- return {
60
- ...baseV1Message,
61
- get json() {
62
- return v2Message.json;
63
- },
64
- toJSON: () => baseV1Message
65
- };
66
- },
67
- configurable: true,
68
- enumerable: true
69
- });
70
- return pubsubEvent;
71
- }
72
- default: return event;
20
+ const memo = {};
21
+ for (const [key, getter] of Object.entries(getters)) {
22
+ Object.defineProperty(event, key, {
23
+ get: () => {
24
+ if (!Object.prototype.hasOwnProperty.call(memo, key)) {
25
+ memo[key] = getter();
26
+ }
27
+ return memo[key];
28
+ },
29
+ configurable: true,
30
+ enumerable: true
31
+ });
73
32
  }
33
+ return event;
74
34
  }
75
35
 
76
36
  //#endregion
77
- export { patchV1Compat };
37
+ export { addV1Compat };
@@ -5,13 +5,13 @@ import { Change } from "../common/change.mjs";
5
5
  import { onInit } from "../common/onInit.mjs";
6
6
  import { config } from "../v1/config.mjs";
7
7
  import { setGlobalOptions } from "./options.mjs";
8
- import { pubsub_exports } from "./providers/pubsub.mjs";
9
8
  import { dataconnect_doc_exports } from "./dataconnect.doc.mjs";
10
9
  import { alerts_exports } from "./providers/alerts/index.mjs";
11
10
  import { database_exports } from "./providers/database.mjs";
12
11
  import { eventarc_exports } from "./providers/eventarc.mjs";
13
12
  import { https_exports } from "./providers/https.mjs";
14
13
  import { identity_exports } from "./providers/identity.mjs";
14
+ import { pubsub_exports } from "./providers/pubsub.mjs";
15
15
  import { scheduler_exports } from "./providers/scheduler.mjs";
16
16
  import { storage_exports } from "./providers/storage.mjs";
17
17
  import { tasks_exports } from "./providers/tasks.mjs";
@@ -5,15 +5,15 @@ import { setApp } from "../common/app.mjs";
5
5
  import { Change } from "../common/change.mjs";
6
6
  import { onInit } from "../common/onInit.mjs";
7
7
  import { config } from "../v1/config.mjs";
8
- import { setGlobalOptions } from "./options.mjs";
9
- import { pubsub_exports } from "./providers/pubsub.mjs";
10
8
  import "./core.mjs";
9
+ import { setGlobalOptions } from "./options.mjs";
11
10
  import { dataconnect_exports } from "./providers/dataconnect/index.mjs";
12
11
  import { alerts_exports } from "./providers/alerts/index.mjs";
13
12
  import { database_exports } from "./providers/database.mjs";
14
13
  import { eventarc_exports } from "./providers/eventarc.mjs";
15
14
  import { https_exports } from "./providers/https.mjs";
16
15
  import { identity_exports } from "./providers/identity.mjs";
16
+ import { pubsub_exports } from "./providers/pubsub.mjs";
17
17
  import { scheduler_exports } from "./providers/scheduler.mjs";
18
18
  import { storage_exports } from "./providers/storage.mjs";
19
19
  import { tasks_exports } from "./providers/tasks.mjs";
@@ -0,0 +1,187 @@
1
+ import { error } from "../../../logger/index.mjs";
2
+ import { initV2Endpoint } from "../../../runtime/manifest.mjs";
3
+ import { withInit } from "../../../common/onInit.mjs";
4
+ import { HttpsError } from "../../../common/providers/https.mjs";
5
+ import { wrapTraceContext } from "../../trace.mjs";
6
+ import { getGlobalOptions, optionsToEndpoint } from "../../options.mjs";
7
+ import "../https.mjs";
8
+ import { requestTypeName, responseTypeName } from "./types/vertex/v1beta1/index.mjs";
9
+ import { requestTypeName as requestTypeName$1, responseTypeName as responseTypeName$1 } from "./types/gemini/v1beta/index.mjs";
10
+
11
+ //#region src/v2/providers/ai/index.ts
12
+ const rpcCodeMap = {
13
+ ok: 0,
14
+ cancelled: 1,
15
+ unknown: 2,
16
+ "invalid-argument": 3,
17
+ "deadline-exceeded": 4,
18
+ "not-found": 5,
19
+ "already-exists": 6,
20
+ "permission-denied": 7,
21
+ unauthenticated: 16,
22
+ "resource-exhausted": 8,
23
+ "failed-precondition": 9,
24
+ aborted: 10,
25
+ "out-of-range": 11,
26
+ unimplemented: 12,
27
+ internal: 13,
28
+ unavailable: 14,
29
+ "data-loss": 15
30
+ };
31
+ const beforeGenerateEventType = "google.firebase.ailogic.v1.beforeGenerate";
32
+ const afterGenerateEventType = "google.firebase.ailogic.v1.afterGenerate";
33
+ const geminiV1Beta = "google.ai.generativelanguage.v1beta";
34
+ const vertexV1Beta1 = "google.cloud.aiplatform.v1beta1";
35
+ function beforeGenerateContent(optsOrCb, cb) {
36
+ let opts;
37
+ let handler;
38
+ if (arguments.length === 1) {
39
+ opts = {};
40
+ handler = optsOrCb;
41
+ } else {
42
+ opts = optsOrCb;
43
+ handler = cb;
44
+ }
45
+ let func = async (req, res) => {
46
+ try {
47
+ let event = req.body;
48
+ if (Buffer.isBuffer(event)) {
49
+ try {
50
+ event = JSON.parse(event.toString("utf-8"));
51
+ } catch (e) {
52
+ error("Invalid JSON body (Buffer):", e);
53
+ throw new HttpsError("invalid-argument", "Invalid JSON body", e);
54
+ }
55
+ } else if (typeof event === "string") {
56
+ try {
57
+ event = JSON.parse(event);
58
+ } catch (e) {
59
+ error("Invalid JSON body (String):", e);
60
+ throw new HttpsError("invalid-argument", "Invalid JSON body", e);
61
+ }
62
+ }
63
+ const parsedEvent = event;
64
+ const result = await handler(parsedEvent);
65
+ const responseBody = result || {};
66
+ if (typeof responseBody === "object") {
67
+ const api = parsedEvent.data?.api;
68
+ if (api === geminiV1Beta) {
69
+ responseBody["@type"] = requestTypeName$1;
70
+ } else if (api === vertexV1Beta1) {
71
+ responseBody["@type"] = requestTypeName;
72
+ }
73
+ }
74
+ res.status(200).send(responseBody);
75
+ } catch (err) {
76
+ error("Unhandled error:", err);
77
+ if (err instanceof HttpsError) {
78
+ res.status(500).send({
79
+ code: rpcCodeMap[err.code] || 13,
80
+ message: err.message
81
+ });
82
+ } else {
83
+ res.status(500).send({
84
+ code: 13,
85
+ message: "Internal error."
86
+ });
87
+ }
88
+ }
89
+ };
90
+ func.run = handler;
91
+ func = wrapTraceContext(withInit(func));
92
+ const baseOpts = optionsToEndpoint(getGlobalOptions());
93
+ const specificOpts = optionsToEndpoint(opts);
94
+ func.__endpoint = {
95
+ ...initV2Endpoint(getGlobalOptions(), opts),
96
+ platform: "gcfv2",
97
+ ...baseOpts,
98
+ ...specificOpts,
99
+ labels: {
100
+ ...baseOpts?.labels,
101
+ ...specificOpts?.labels
102
+ },
103
+ blockingTrigger: {
104
+ eventType: beforeGenerateEventType,
105
+ options: { regionalWebhook: opts.regionalWebhook }
106
+ }
107
+ };
108
+ return func;
109
+ }
110
+ function afterGenerateContent(optsOrCb, cb) {
111
+ let opts;
112
+ let handler;
113
+ if (arguments.length === 1) {
114
+ opts = {};
115
+ handler = optsOrCb;
116
+ } else {
117
+ opts = optsOrCb;
118
+ handler = cb;
119
+ }
120
+ let func = async (req, res) => {
121
+ try {
122
+ let event = req.body;
123
+ if (Buffer.isBuffer(event)) {
124
+ try {
125
+ event = JSON.parse(event.toString("utf-8"));
126
+ } catch (e) {
127
+ error("Invalid JSON body (Buffer):", e);
128
+ throw new HttpsError("invalid-argument", "Invalid JSON body", e);
129
+ }
130
+ } else if (typeof event === "string") {
131
+ try {
132
+ event = JSON.parse(event);
133
+ } catch (e) {
134
+ error("Invalid JSON body (String):", e);
135
+ throw new HttpsError("invalid-argument", "Invalid JSON body", e);
136
+ }
137
+ }
138
+ const parsedEvent = event;
139
+ const result = await handler(parsedEvent);
140
+ const responseBody = result || {};
141
+ if (typeof responseBody === "object") {
142
+ const api = parsedEvent.data?.api;
143
+ if (api === geminiV1Beta) {
144
+ responseBody["@type"] = responseTypeName$1;
145
+ } else if (api === vertexV1Beta1) {
146
+ responseBody["@type"] = responseTypeName;
147
+ }
148
+ }
149
+ res.status(200).send(responseBody);
150
+ } catch (err) {
151
+ error("Unhandled error:", err);
152
+ if (err instanceof HttpsError) {
153
+ res.status(500).send({
154
+ code: rpcCodeMap[err.code] || 13,
155
+ message: err.message
156
+ });
157
+ } else {
158
+ res.status(500).send({
159
+ code: 13,
160
+ message: "Internal error."
161
+ });
162
+ }
163
+ }
164
+ };
165
+ func.run = handler;
166
+ func = wrapTraceContext(withInit(func));
167
+ const baseOpts = optionsToEndpoint(getGlobalOptions());
168
+ const specificOpts = optionsToEndpoint(opts);
169
+ func.__endpoint = {
170
+ ...initV2Endpoint(getGlobalOptions(), opts),
171
+ platform: "gcfv2",
172
+ ...baseOpts,
173
+ ...specificOpts,
174
+ labels: {
175
+ ...baseOpts?.labels,
176
+ ...specificOpts?.labels
177
+ },
178
+ blockingTrigger: {
179
+ eventType: afterGenerateEventType,
180
+ options: { regionalWebhook: opts.regionalWebhook }
181
+ }
182
+ };
183
+ return func;
184
+ }
185
+
186
+ //#endregion
187
+ export { GeminiV1BetaGenerateContentRequest, GeminiV1BetaGenerateContentResponse, HttpsError, VertexV1Beta1GenerateContentRequest, VertexV1Beta1GenerateContentResponse, afterGenerateContent, afterGenerateEventType, beforeGenerateContent, beforeGenerateEventType, geminiV1Beta, rpcCodeMap, vertexV1Beta1 };
@@ -0,0 +1,6 @@
1
+ //#region src/v2/providers/ai/types/gemini/v1beta/index.ts
2
+ const requestTypeName = "type.googleapis.com/google.ai.generativelanguage.v1beta.GenerateContentRequest";
3
+ const responseTypeName = "type.googleapis.com/google.ai.generativelanguage.v1beta.GenerateContentResponse";
4
+
5
+ //#endregion
6
+ export { requestTypeName, responseTypeName };
@@ -0,0 +1,6 @@
1
+ //#region src/v2/providers/ai/types/vertex/v1beta1/index.ts
2
+ const requestTypeName = "type.googleapis.com/google.cloud.aiplatform.v1beta1.GenerateContentRequest";
3
+ const responseTypeName = "type.googleapis.com/google.cloud.aiplatform.v1beta1.GenerateContentResponse";
4
+
5
+ //#endregion
6
+ export { requestTypeName, responseTypeName };
@@ -6,6 +6,7 @@ import { normalizePath } from "../../common/utilities/path.mjs";
6
6
  import { DataSnapshot } from "../../common/providers/database.mjs";
7
7
  import { applyChange } from "../../common/utilities/utils.mjs";
8
8
  import { wrapTraceContext } from "../trace.mjs";
9
+ import { addV1Compat } from "../compat.mjs";
9
10
  import { getGlobalOptions, optionsToEndpoint } from "../options.mjs";
10
11
  import { PathPattern } from "../../common/utilities/path-pattern.mjs";
11
12
 
@@ -135,6 +136,30 @@ function makeChangedDatabaseEvent(event, instance, params) {
135
136
  delete databaseEvent.authid;
136
137
  return databaseEvent;
137
138
  }
139
+ function makeV1Context(eventType, databaseEvent) {
140
+ return {
141
+ eventId: databaseEvent.id,
142
+ timestamp: databaseEvent.time,
143
+ eventType: {
144
+ [writtenEventType]: "providers/google.firebase.database/eventTypes/ref.write",
145
+ [createdEventType]: "providers/google.firebase.database/eventTypes/ref.create",
146
+ [updatedEventType]: "providers/google.firebase.database/eventTypes/ref.update",
147
+ [deletedEventType]: "providers/google.firebase.database/eventTypes/ref.delete"
148
+ }[eventType] || eventType,
149
+ resource: {
150
+ service: "firebaseio.com",
151
+ name: `projects/_/instances/${databaseEvent.instance}/refs/${databaseEvent.ref}`
152
+ },
153
+ params: databaseEvent.params,
154
+ ...databaseEvent.authType === "admin" ? { authType: "ADMIN" } : databaseEvent.authType === "unauthenticated" ? { authType: "UNAUTHENTICATED" } : databaseEvent.authType === "app_user" ? {
155
+ authType: "USER",
156
+ auth: {
157
+ uid: databaseEvent.authId || "",
158
+ token: {}
159
+ }
160
+ } : {}
161
+ };
162
+ }
138
163
  /** @internal */
139
164
  function makeEndpoint(eventType, opts, path, instance) {
140
165
  const baseOpts = optionsToEndpoint(getGlobalOptions());
@@ -173,7 +198,11 @@ function onChangedOperation(eventType, referenceOrOpts, handler) {
173
198
  const instanceUrl = getInstance(event);
174
199
  const params = makeParams(event, pathPattern, instancePattern);
175
200
  const databaseEvent = makeChangedDatabaseEvent(event, instanceUrl, params);
176
- return wrapTraceContext(withInit(handler))(databaseEvent);
201
+ const compatEvent = addV1Compat(databaseEvent, {
202
+ context: () => makeV1Context(eventType, databaseEvent),
203
+ change: () => databaseEvent.data
204
+ });
205
+ return wrapTraceContext(withInit(handler))(compatEvent);
177
206
  };
178
207
  func.run = handler;
179
208
  func.__endpoint = makeEndpoint(eventType, opts, pathPattern, instancePattern);
@@ -190,7 +219,11 @@ function onOperation(eventType, referenceOrOpts, handler) {
190
219
  const params = makeParams(event, pathPattern, instancePattern);
191
220
  const data = eventType === deletedEventType ? event.data.data : event.data.delta;
192
221
  const databaseEvent = makeDatabaseEvent(event, data, instanceUrl, params);
193
- return wrapTraceContext(withInit(handler))(databaseEvent);
222
+ const compatEvent = addV1Compat(databaseEvent, {
223
+ context: () => makeV1Context(eventType, databaseEvent),
224
+ snapshot: () => databaseEvent.data
225
+ });
226
+ return wrapTraceContext(withInit(handler))(compatEvent);
194
227
  };
195
228
  func.run = handler;
196
229
  func.__endpoint = makeEndpoint(eventType, opts, pathPattern, instancePattern);
@@ -6,8 +6,9 @@ import { withInit } from "../../common/onInit.mjs";
6
6
  import { normalizePath } from "../../common/utilities/path.mjs";
7
7
  import { createBeforeSnapshotFromJson, createBeforeSnapshotFromProtobuf, createSnapshotFromJson, createSnapshotFromProtobuf } from "../../common/providers/firestore.mjs";
8
8
  import { wrapTraceContext } from "../trace.mjs";
9
- import { getGlobalOptions, optionsToEndpoint } from "../options.mjs";
9
+ import { addV1Compat } from "../compat.mjs";
10
10
  import "../core.mjs";
11
+ import { getGlobalOptions, optionsToEndpoint } from "../options.mjs";
11
12
  import { PathPattern } from "../../common/utilities/path-pattern.mjs";
12
13
 
13
14
  //#region src/v2/providers/firestore.ts
@@ -20,6 +21,7 @@ var firestore_exports = /* @__PURE__ */ __export({
20
21
  deletedEventType: () => deletedEventType,
21
22
  deletedEventWithAuthContextType: () => deletedEventWithAuthContextType,
22
23
  getOpts: () => getOpts,
24
+ getV1Context: () => getV1Context,
23
25
  makeChangedFirestoreEvent: () => makeChangedFirestoreEvent,
24
26
  makeEndpoint: () => makeEndpoint,
25
27
  makeFirestoreEvent: () => makeFirestoreEvent,
@@ -68,7 +70,7 @@ function onDocumentWritten(documentOrOpts, handler) {
68
70
  * Event handler that triggers when a document is created, updated, or deleted in Firestore.
69
71
  * This trigger also provides the authentication context of the principal who triggered the event.
70
72
  *
71
- * @param opts - Options or a string document path.
73
+ * @param documentOrOpts - Options or a string document path.
72
74
  * @param handler - Event handler which is run every time a Firestore create, update, or delete occurs.
73
75
  */
74
76
  function onDocumentWrittenWithAuthContext(documentOrOpts, handler) {
@@ -262,6 +264,29 @@ function makeEndpoint(eventType, opts, document, database, namespace) {
262
264
  };
263
265
  }
264
266
  /** @internal */
267
+ function getV1Context(event) {
268
+ return {
269
+ eventId: event.id,
270
+ timestamp: event.time,
271
+ eventType: {
272
+ "google.cloud.firestore.document.v1.written": "providers/cloud.firestore/eventTypes/document.write",
273
+ "google.cloud.firestore.document.v1.created": "providers/cloud.firestore/eventTypes/document.create",
274
+ "google.cloud.firestore.document.v1.updated": "providers/cloud.firestore/eventTypes/document.update",
275
+ "google.cloud.firestore.document.v1.deleted": "providers/cloud.firestore/eventTypes/document.delete",
276
+ "google.cloud.firestore.document.v1.written.withAuthContext": "providers/cloud.firestore/eventTypes/document.write",
277
+ "google.cloud.firestore.document.v1.created.withAuthContext": "providers/cloud.firestore/eventTypes/document.create",
278
+ "google.cloud.firestore.document.v1.updated.withAuthContext": "providers/cloud.firestore/eventTypes/document.update",
279
+ "google.cloud.firestore.document.v1.deleted.withAuthContext": "providers/cloud.firestore/eventTypes/document.delete"
280
+ }[event.type] || event.type,
281
+ resource: {
282
+ service: "firestore.googleapis.com",
283
+ name: `projects/${event.project}/databases/${event.database}/documents/${event.document}`
284
+ },
285
+ params: event.params,
286
+ authType: event.authType,
287
+ authId: event.authId
288
+ };
289
+ }
265
290
  function onOperation(eventType, documentOrOpts, handler) {
266
291
  const { document, database, namespace, opts } = getOpts(documentOrOpts);
267
292
  const func = (raw) => {
@@ -269,13 +294,16 @@ function onOperation(eventType, documentOrOpts, handler) {
269
294
  const documentPattern = new PathPattern(typeof document === "string" ? document : document.value());
270
295
  const params = makeParams(event.document, documentPattern);
271
296
  const firestoreEvent = makeFirestoreEvent(eventType, event, params);
272
- return wrapTraceContext(withInit(handler))(firestoreEvent);
297
+ const patchedEvent = addV1Compat(firestoreEvent, {
298
+ context: () => getV1Context(firestoreEvent),
299
+ snapshot: () => firestoreEvent.data
300
+ });
301
+ return wrapTraceContext(withInit(handler))(patchedEvent);
273
302
  };
274
303
  func.run = handler;
275
304
  func.__endpoint = makeEndpoint(eventType, opts, document, database, namespace);
276
305
  return func;
277
306
  }
278
- /** @internal */
279
307
  function onChangedOperation(eventType, documentOrOpts, handler) {
280
308
  const { document, database, namespace, opts } = getOpts(documentOrOpts);
281
309
  const func = (raw) => {
@@ -283,7 +311,11 @@ function onChangedOperation(eventType, documentOrOpts, handler) {
283
311
  const documentPattern = new PathPattern(typeof document === "string" ? document : document.value());
284
312
  const params = makeParams(event.document, documentPattern);
285
313
  const firestoreEvent = makeChangedFirestoreEvent(event, params);
286
- return wrapTraceContext(withInit(handler))(firestoreEvent);
314
+ const patchedEvent = addV1Compat(firestoreEvent, {
315
+ context: () => getV1Context(firestoreEvent),
316
+ change: () => firestoreEvent.data
317
+ });
318
+ return wrapTraceContext(withInit(handler))(patchedEvent);
287
319
  };
288
320
  func.run = handler;
289
321
  func.__endpoint = makeEndpoint(eventType, opts, document, database, namespace);
@@ -291,4 +323,4 @@ function onChangedOperation(eventType, documentOrOpts, handler) {
291
323
  }
292
324
 
293
325
  //#endregion
294
- export { Change, createBeforeSnapshot, createSnapshot, createdEventType, createdEventWithAuthContextType, deletedEventType, deletedEventWithAuthContextType, firestore_exports, getOpts, makeChangedFirestoreEvent, makeEndpoint, makeFirestoreEvent, makeParams, onChangedOperation, onDocumentCreated, onDocumentCreatedWithAuthContext, onDocumentDeleted, onDocumentDeletedWithAuthContext, onDocumentUpdated, onDocumentUpdatedWithAuthContext, onDocumentWritten, onDocumentWrittenWithAuthContext, onOperation, updatedEventType, updatedEventWithAuthContextType, writtenEventType, writtenEventWithAuthContextType };
326
+ export { Change, createBeforeSnapshot, createSnapshot, createdEventType, createdEventWithAuthContextType, deletedEventType, deletedEventWithAuthContextType, firestore_exports, getOpts, getV1Context, makeChangedFirestoreEvent, makeEndpoint, makeFirestoreEvent, makeParams, onChangedOperation, onDocumentCreated, onDocumentCreatedWithAuthContext, onDocumentDeleted, onDocumentDeletedWithAuthContext, onDocumentUpdated, onDocumentUpdatedWithAuthContext, onDocumentWritten, onDocumentWrittenWithAuthContext, onOperation, updatedEventType, updatedEventWithAuthContextType, writtenEventType, writtenEventWithAuthContextType };
@@ -128,13 +128,21 @@ function onCall(optsOrHandler, handler) {
128
128
  origin = origin[0];
129
129
  }
130
130
  const fixedLen = (req, resp) => handler(req, resp);
131
+ let enforceAppCheck = opts.enforceAppCheck ?? getGlobalOptions().enforceAppCheck;
132
+ if (enforceAppCheck instanceof Expression) {
133
+ enforceAppCheck = enforceAppCheck.value();
134
+ }
135
+ let consumeAppCheckToken = opts.consumeAppCheckToken;
136
+ if (consumeAppCheckToken instanceof Expression) {
137
+ consumeAppCheckToken = consumeAppCheckToken.value();
138
+ }
131
139
  let func = onCallHandler({
132
140
  cors: {
133
141
  origin,
134
142
  methods: "POST"
135
143
  },
136
- enforceAppCheck: opts.enforceAppCheck ?? getGlobalOptions().enforceAppCheck,
137
- consumeAppCheckToken: opts.consumeAppCheckToken,
144
+ enforceAppCheck,
145
+ consumeAppCheckToken,
138
146
  heartbeatSeconds: opts.heartbeatSeconds,
139
147
  authPolicy: opts.authPolicy
140
148
  }, fixedLen, "gcfv2");
@@ -3,8 +3,8 @@ import { initV2Endpoint } from "../../runtime/manifest.mjs";
3
3
  import { copyIfPresent } from "../../common/encoding.mjs";
4
4
  import { withInit } from "../../common/onInit.mjs";
5
5
  import { wrapTraceContext } from "../trace.mjs";
6
+ import { addV1Compat } from "../compat.mjs";
6
7
  import { getGlobalOptions, optionsToEndpoint, optionsToTriggerAnnotations } from "../options.mjs";
7
- import { patchV1Compat } from "../compat.mjs";
8
8
 
9
9
  //#region src/v2/providers/pubsub.ts
10
10
  var pubsub_exports = /* @__PURE__ */ __export({
@@ -99,7 +99,47 @@ function onMessagePublished(topicOrOptions, handler) {
99
99
  delete opts.topic;
100
100
  }
101
101
  const func = (raw) => {
102
- const event = patchV1Compat(raw);
102
+ const pubsubEvent = raw;
103
+ const pubsubData = pubsubEvent.data;
104
+ let v2Message;
105
+ if (pubsubData && pubsubData.message) {
106
+ v2Message = pubsubData.message instanceof Message ? pubsubData.message : new Message(pubsubData.message);
107
+ pubsubData.message = v2Message;
108
+ } else {
109
+ throw new Error("Malformed Pub/Sub event: missing 'message' property.");
110
+ }
111
+ const event = addV1Compat(pubsubEvent, {
112
+ context: () => {
113
+ const service = "pubsub.googleapis.com";
114
+ const sourcePrefix = `//${service}/`;
115
+ return {
116
+ eventId: v2Message.messageId,
117
+ timestamp: v2Message.publishTime,
118
+ eventType: "google.pubsub.topic.publish",
119
+ resource: {
120
+ service,
121
+ name: raw.source?.startsWith(sourcePrefix) ? raw.source.substring(sourcePrefix.length) : raw.source || ""
122
+ },
123
+ params: {}
124
+ };
125
+ },
126
+ message: () => {
127
+ const baseV1Message = {
128
+ data: v2Message.data,
129
+ messageId: v2Message.messageId,
130
+ publishTime: v2Message.publishTime,
131
+ attributes: v2Message.attributes,
132
+ ...v2Message.orderingKey && { orderingKey: v2Message.orderingKey }
133
+ };
134
+ return {
135
+ ...baseV1Message,
136
+ get json() {
137
+ return v2Message.json;
138
+ },
139
+ toJSON: () => baseV1Message
140
+ };
141
+ }
142
+ });
103
143
  return wrapTraceContext(withInit(handler))(event);
104
144
  };
105
145
  func.run = handler;