1 | ;
|
2 | // The MIT License (MIT)
|
3 | //
|
4 | // Copyright (c) 2022 Firebase
|
5 | //
|
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | // of this software and associated documentation files (the "Software"), to deal
|
8 | // in the Software without restriction, including without limitation the rights
|
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | // copies of the Software, and to permit persons to whom the Software is
|
11 | // furnished to do so, subject to the following conditions:
|
12 | //
|
13 | // The above copyright notice and this permission notice shall be included in all
|
14 | // copies or substantial portions of the Software.
|
15 | //
|
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22 | // SOFTWARE.
|
23 | Object.defineProperty(exports, "__esModule", { value: true });
|
24 | exports.getOptsAndBucket = exports.onOperation = exports.onObjectMetadataUpdated = exports.onObjectDeleted = exports.onObjectFinalized = exports.onObjectArchived = exports.metadataUpdatedEvent = exports.deletedEvent = exports.finalizedEvent = exports.archivedEvent = void 0;
|
25 | /**
|
26 | * Cloud functions to handle events from Google Cloud Storage.
|
27 | * @packageDocumentation
|
28 | */
|
29 | const config_1 = require("../../common/config");
|
30 | const encoding_1 = require("../../common/encoding");
|
31 | const manifest_1 = require("../../runtime/manifest");
|
32 | const trace_1 = require("../trace");
|
33 | const options = require("../options");
|
34 | const onInit_1 = require("../../common/onInit");
|
35 | /** @internal */
|
36 | exports.archivedEvent = "google.cloud.storage.object.v1.archived";
|
37 | /** @internal */
|
38 | exports.finalizedEvent = "google.cloud.storage.object.v1.finalized";
|
39 | /** @internal */
|
40 | exports.deletedEvent = "google.cloud.storage.object.v1.deleted";
|
41 | /** @internal */
|
42 | exports.metadataUpdatedEvent = "google.cloud.storage.object.v1.metadataUpdated";
|
43 | /**
|
44 | * Event handler sent only when a bucket has enabled object versioning.
|
45 | * This event indicates that the live version of an object has become an
|
46 | * archived version, either because it was archived or because it was
|
47 | * overwritten by the upload of an object of the same name.
|
48 | *
|
49 | * @param bucketOrOptsOrHandler - Options or string that may (or may not) define the bucket to be used.
|
50 | * @param handler - Event handler which is run every time a Google Cloud Storage archival occurs.
|
51 | */
|
52 | function onObjectArchived(bucketOrOptsOrHandler, handler) {
|
53 | return onOperation(exports.archivedEvent, bucketOrOptsOrHandler, handler);
|
54 | }
|
55 | exports.onObjectArchived = onObjectArchived;
|
56 | /**
|
57 | * Event handler which fires every time a Google Cloud Storage object
|
58 | * creation occurs.
|
59 | *
|
60 | * Sent when a new object (or a new generation of an existing object)
|
61 | * is successfully created in the bucket. This includes copying or rewriting
|
62 | * an existing object. A failed upload does not trigger this event.
|
63 | *
|
64 | * @param bucketOrOptsOrHandler - Options or string that may (or may not) define the bucket to be used.
|
65 | * @param handler - Event handler which is run every time a Google Cloud Storage object creation occurs.
|
66 | */
|
67 | function onObjectFinalized(bucketOrOptsOrHandler, handler) {
|
68 | return onOperation(exports.finalizedEvent, bucketOrOptsOrHandler, handler);
|
69 | }
|
70 | exports.onObjectFinalized = onObjectFinalized;
|
71 | /**
|
72 | * Event handler which fires every time a Google Cloud Storage deletion occurs.
|
73 | *
|
74 | * Sent when an object has been permanently deleted. This includes objects
|
75 | * that are overwritten or are deleted as part of the bucket's lifecycle
|
76 | * configuration. For buckets with object versioning enabled, this is not
|
77 | * sent when an object is archived, even if archival occurs
|
78 | * via the `storage.objects.delete` method.
|
79 | *
|
80 | * @param bucketOrOptsOrHandler - Options or string that may (or may not) define the bucket to be used.
|
81 | * @param handler - Event handler which is run every time a Google Cloud Storage object deletion occurs.
|
82 | */
|
83 | function onObjectDeleted(bucketOrOptsOrHandler, handler) {
|
84 | return onOperation(exports.deletedEvent, bucketOrOptsOrHandler, handler);
|
85 | }
|
86 | exports.onObjectDeleted = onObjectDeleted;
|
87 | /**
|
88 | * Event handler which fires every time the metadata of an existing object
|
89 | * changes.
|
90 | *
|
91 | * @param bucketOrOptsOrHandler - Options or string that may (or may not) define the bucket to be used.
|
92 | * @param handler - Event handler which is run every time a Google Cloud Storage object metadata update occurs.
|
93 | */
|
94 | function onObjectMetadataUpdated(bucketOrOptsOrHandler, handler) {
|
95 | return onOperation(exports.metadataUpdatedEvent, bucketOrOptsOrHandler, handler);
|
96 | }
|
97 | exports.onObjectMetadataUpdated = onObjectMetadataUpdated;
|
98 | /** @internal */
|
99 | function onOperation(eventType, bucketOrOptsOrHandler, handler) {
|
100 | if (typeof bucketOrOptsOrHandler === "function") {
|
101 | handler = bucketOrOptsOrHandler;
|
102 | bucketOrOptsOrHandler = {};
|
103 | }
|
104 | const [opts, bucket] = getOptsAndBucket(bucketOrOptsOrHandler);
|
105 | const func = (raw) => {
|
106 | return (0, trace_1.wrapTraceContext)((0, onInit_1.withInit)(handler))(raw);
|
107 | };
|
108 | func.run = handler;
|
109 | Object.defineProperty(func, "__trigger", {
|
110 | get: () => {
|
111 | const baseOpts = options.optionsToTriggerAnnotations(options.getGlobalOptions());
|
112 | const specificOpts = options.optionsToTriggerAnnotations(opts);
|
113 | return {
|
114 | platform: "gcfv2",
|
115 | ...baseOpts,
|
116 | ...specificOpts,
|
117 | labels: {
|
118 | ...baseOpts === null || baseOpts === void 0 ? void 0 : baseOpts.labels,
|
119 | ...specificOpts === null || specificOpts === void 0 ? void 0 : specificOpts.labels,
|
120 | },
|
121 | eventTrigger: {
|
122 | eventType,
|
123 | resource: bucket, // TODO(colerogers): replace with 'bucket,' eventually
|
124 | },
|
125 | };
|
126 | },
|
127 | });
|
128 | // TypeScript doesn't recognize defineProperty as adding a property and complains
|
129 | // that __endpoint doesn't exist. We can either cast to any and lose all type safety
|
130 | // or we can just assign a meaningless value before calling defineProperty.
|
131 | func.__endpoint = {};
|
132 | // SDK may attempt to read FIREBASE_CONFIG env var to fetch the default bucket name.
|
133 | // To prevent runtime errors when FIREBASE_CONFIG env var is missing, we use getters.
|
134 | Object.defineProperty(func, "__endpoint", {
|
135 | get: () => {
|
136 | var _a;
|
137 | const baseOpts = options.optionsToEndpoint(options.getGlobalOptions());
|
138 | const specificOpts = options.optionsToEndpoint(opts);
|
139 | const endpoint = {
|
140 | platform: "gcfv2",
|
141 | ...(0, manifest_1.initV2Endpoint)(options.getGlobalOptions(), opts),
|
142 | ...baseOpts,
|
143 | ...specificOpts,
|
144 | labels: {
|
145 | ...baseOpts === null || baseOpts === void 0 ? void 0 : baseOpts.labels,
|
146 | ...specificOpts === null || specificOpts === void 0 ? void 0 : specificOpts.labels,
|
147 | },
|
148 | eventTrigger: {
|
149 | eventType,
|
150 | eventFilters: { bucket },
|
151 | retry: (_a = opts.retry) !== null && _a !== void 0 ? _a : false,
|
152 | },
|
153 | };
|
154 | (0, encoding_1.copyIfPresent)(endpoint.eventTrigger, opts, "retry", "retry");
|
155 | return endpoint;
|
156 | },
|
157 | });
|
158 | return func;
|
159 | }
|
160 | exports.onOperation = onOperation;
|
161 | /** @internal */
|
162 | function getOptsAndBucket(bucketOrOpts) {
|
163 | var _a;
|
164 | let bucket;
|
165 | let opts;
|
166 | // If bucket is a string or Expression<string>
|
167 | if (typeof bucketOrOpts === "string" || "value" in bucketOrOpts) {
|
168 | bucket = bucketOrOpts;
|
169 | opts = {};
|
170 | }
|
171 | else {
|
172 | bucket = bucketOrOpts.bucket || ((_a = (0, config_1.firebaseConfig)()) === null || _a === void 0 ? void 0 : _a.storageBucket);
|
173 | opts = { ...bucketOrOpts };
|
174 | delete opts.bucket;
|
175 | }
|
176 | if (!bucket) {
|
177 | throw new Error("Missing bucket name. If you are unit testing, please provide a bucket name" +
|
178 | " by providing bucket name directly in the event handler or by setting process.env.FIREBASE_CONFIG.");
|
179 | }
|
180 | if (typeof bucket === "string" && !/^[a-z\d][a-z\d\\._-]{1,230}[a-z\d]$/.test(bucket)) {
|
181 | throw new Error(`Invalid bucket name ${bucket}`);
|
182 | }
|
183 | return [opts, bucket];
|
184 | }
|
185 | exports.getOptsAndBucket = getOptsAndBucket;
|