firebase-tools 10.5.0 → 10.6.0
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.
- package/lib/commands/functions-secrets-destroy.js +23 -3
- package/lib/commands/functions-secrets-prune.js +15 -12
- package/lib/commands/functions-secrets-set.js +51 -4
- package/lib/deploy/functions/backend.js +1 -5
- package/lib/deploy/functions/prepare.js +13 -3
- package/lib/deploy/functions/release/fabricator.js +1 -3
- package/lib/deploy/functions/release/index.js +21 -0
- package/lib/deploy/functions/release/planner.js +1 -2
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +11 -10
- package/lib/deploy/functions/runtimes/node/index.js +1 -1
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +5 -19
- package/lib/deploy/functions/services/storage.js +1 -6
- package/lib/emulator/extensions/postinstall.js +41 -0
- package/lib/emulator/functionsEmulatorShared.js +16 -20
- package/lib/emulator/storage/apis/firebase.js +6 -6
- package/lib/emulator/storage/apis/gcloud.js +9 -6
- package/lib/emulator/storage/files.js +6 -3
- package/lib/emulator/storage/index.js +9 -1
- package/lib/emulator/storage/metadata.js +18 -8
- package/lib/emulator/storage/rules/manager.js +7 -17
- package/lib/emulator/storage/server.js +38 -12
- package/lib/extensions/askUserForParam.js +14 -11
- package/lib/extensions/emulator/optionsHelper.js +5 -7
- package/lib/extensions/emulator/triggerHelper.js +11 -14
- package/lib/extensions/extensionsApi.js +2 -1
- package/lib/extensions/manifest.js +1 -1
- package/lib/extensions/paramHelper.js +16 -10
- package/lib/functions/env.js +10 -2
- package/lib/functions/runtimeConfigExport.js +10 -6
- package/lib/functions/secrets.js +99 -6
- package/lib/gcp/cloudfunctions.js +6 -13
- package/lib/gcp/cloudfunctionsv2.js +14 -23
- package/lib/gcp/cloudtasks.js +5 -3
- package/lib/gcp/secretManager.js +1 -1
- package/lib/utils.js +30 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/lib/functions/secrets.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pruneSecrets = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.labels = exports.isFirebaseManaged = void 0;
|
|
3
|
+
exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.inUse = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.labels = exports.isFirebaseManaged = void 0;
|
|
4
|
+
const utils = require("../utils");
|
|
5
|
+
const poller = require("../operation-poller");
|
|
6
|
+
const gcf = require("../gcp/cloudfunctions");
|
|
4
7
|
const secretManager_1 = require("../gcp/secretManager");
|
|
5
8
|
const error_1 = require("../error");
|
|
6
9
|
const utils_1 = require("../utils");
|
|
7
10
|
const prompt_1 = require("../prompt");
|
|
8
11
|
const env_1 = require("./env");
|
|
12
|
+
const logger_1 = require("../logger");
|
|
13
|
+
const api_1 = require("../api");
|
|
14
|
+
const functional_1 = require("../functional");
|
|
9
15
|
const FIREBASE_MANGED = "firebase-managed";
|
|
10
16
|
function isFirebaseManaged(secret) {
|
|
11
17
|
return Object.keys(secret.labels || []).includes(FIREBASE_MANGED);
|
|
@@ -17,8 +23,7 @@ function labels() {
|
|
|
17
23
|
exports.labels = labels;
|
|
18
24
|
function toUpperSnakeCase(key) {
|
|
19
25
|
return key
|
|
20
|
-
.replace(
|
|
21
|
-
.replace(".", "_")
|
|
26
|
+
.replace(/[.-]/g, "_")
|
|
22
27
|
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
|
23
28
|
.toUpperCase();
|
|
24
29
|
}
|
|
@@ -80,19 +85,40 @@ function of(endpoints) {
|
|
|
80
85
|
return endpoints.reduce((envs, endpoint) => [...envs, ...(endpoint.secretEnvironmentVariables || [])], []);
|
|
81
86
|
}
|
|
82
87
|
exports.of = of;
|
|
88
|
+
function inUse(projectInfo, secret, endpoint) {
|
|
89
|
+
const { projectId, projectNumber } = projectInfo;
|
|
90
|
+
for (const sev of of([endpoint])) {
|
|
91
|
+
if ((sev.projectId === projectId || sev.projectId === projectNumber) &&
|
|
92
|
+
sev.secret === secret.name) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
exports.inUse = inUse;
|
|
83
99
|
async function pruneSecrets(projectInfo, endpoints) {
|
|
84
100
|
const { projectId, projectNumber } = projectInfo;
|
|
85
101
|
const pruneKey = (name, version) => `${name}@${version}`;
|
|
86
102
|
const prunedSecrets = new Set();
|
|
87
103
|
const haveSecrets = await (0, secretManager_1.listSecrets)(projectId, `labels.${FIREBASE_MANGED}=true`);
|
|
88
104
|
for (const secret of haveSecrets) {
|
|
89
|
-
const versions = await (0, secretManager_1.listSecretVersions)(projectId, secret.name, `state:
|
|
105
|
+
const versions = await (0, secretManager_1.listSecretVersions)(projectId, secret.name, `NOT state: DESTROYED`);
|
|
90
106
|
for (const version of versions) {
|
|
91
107
|
prunedSecrets.add(pruneKey(secret.name, version.versionId));
|
|
92
108
|
}
|
|
93
109
|
}
|
|
94
|
-
const
|
|
95
|
-
for (const
|
|
110
|
+
const secrets = [];
|
|
111
|
+
for (const secret of of(endpoints)) {
|
|
112
|
+
if (!secret.version) {
|
|
113
|
+
throw new error_1.FirebaseError(`Secret ${secret.secret} version is unexpectedly empty.`);
|
|
114
|
+
}
|
|
115
|
+
if (secret.projectId === projectId || secret.projectId === projectNumber) {
|
|
116
|
+
if (secret.version) {
|
|
117
|
+
secrets.push(Object.assign(Object.assign({}, secret), { version: secret.version }));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const sev of secrets) {
|
|
96
122
|
let name = sev.secret;
|
|
97
123
|
if (name.includes("/")) {
|
|
98
124
|
const secret = (0, secretManager_1.parseSecretResourceName)(name);
|
|
@@ -110,3 +136,70 @@ async function pruneSecrets(projectInfo, endpoints) {
|
|
|
110
136
|
.map(([secret, version]) => ({ projectId, version, secret, key: secret }));
|
|
111
137
|
}
|
|
112
138
|
exports.pruneSecrets = pruneSecrets;
|
|
139
|
+
async function pruneAndDestroySecrets(projectInfo, endpoints) {
|
|
140
|
+
const { projectId, projectNumber } = projectInfo;
|
|
141
|
+
logger_1.logger.debug("Pruning secrets to find unused secret versions...");
|
|
142
|
+
const unusedSecrets = await module.exports.pruneSecrets({ projectId, projectNumber }, endpoints);
|
|
143
|
+
if (unusedSecrets.length === 0) {
|
|
144
|
+
return { destroyed: [], erred: [] };
|
|
145
|
+
}
|
|
146
|
+
const destroyed = [];
|
|
147
|
+
const erred = [];
|
|
148
|
+
const msg = unusedSecrets.map((s) => `${s.secret}@${s.version}`);
|
|
149
|
+
logger_1.logger.debug(`Found unused secret versions: ${msg}. Destroying them...`);
|
|
150
|
+
const destroyResults = await utils.allSettled(unusedSecrets.map(async (sev) => {
|
|
151
|
+
await (0, secretManager_1.destroySecretVersion)(sev.projectId, sev.secret, sev.version);
|
|
152
|
+
return sev;
|
|
153
|
+
}));
|
|
154
|
+
for (const result of destroyResults) {
|
|
155
|
+
if (result.status === "fulfilled") {
|
|
156
|
+
destroyed.push(result.value);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
erred.push(result.reason);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { destroyed, erred };
|
|
163
|
+
}
|
|
164
|
+
exports.pruneAndDestroySecrets = pruneAndDestroySecrets;
|
|
165
|
+
async function updateEndpointSecret(projectInfo, secretVersion, endpoint) {
|
|
166
|
+
const { projectId, projectNumber } = projectInfo;
|
|
167
|
+
if (!inUse(projectInfo, secretVersion.secret, endpoint)) {
|
|
168
|
+
return endpoint;
|
|
169
|
+
}
|
|
170
|
+
const updatedSevs = [];
|
|
171
|
+
for (const sev of of([endpoint])) {
|
|
172
|
+
const updatedSev = Object.assign({}, sev);
|
|
173
|
+
if ((updatedSev.projectId === projectId || updatedSev.projectId === projectNumber) &&
|
|
174
|
+
updatedSev.secret === secretVersion.secret.name) {
|
|
175
|
+
updatedSev.version = secretVersion.versionId;
|
|
176
|
+
}
|
|
177
|
+
updatedSevs.push(updatedSev);
|
|
178
|
+
}
|
|
179
|
+
if (endpoint.platform === "gcfv1") {
|
|
180
|
+
const fn = gcf.functionFromEndpoint(endpoint, "");
|
|
181
|
+
const op = await gcf.updateFunction({
|
|
182
|
+
name: fn.name,
|
|
183
|
+
runtime: fn.runtime,
|
|
184
|
+
entryPoint: fn.entryPoint,
|
|
185
|
+
secretEnvironmentVariables: updatedSevs,
|
|
186
|
+
});
|
|
187
|
+
const gcfV1PollerOptions = {
|
|
188
|
+
apiOrigin: api_1.functionsOrigin,
|
|
189
|
+
apiVersion: gcf.API_VERSION,
|
|
190
|
+
masterTimeout: 25 * 60 * 1000,
|
|
191
|
+
maxBackoff: 10000,
|
|
192
|
+
pollerName: `update-${endpoint.region}-${endpoint.id}`,
|
|
193
|
+
operationResourceName: op.name,
|
|
194
|
+
};
|
|
195
|
+
const cfn = await poller.pollOperation(gcfV1PollerOptions);
|
|
196
|
+
return gcf.endpointFromFunction(cfn);
|
|
197
|
+
}
|
|
198
|
+
else if (endpoint.platform === "gcfv2") {
|
|
199
|
+
throw new error_1.FirebaseError(`Unsupported platform ${endpoint.platform}`);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
(0, functional_1.assertExhaustive)(endpoint.platform);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
exports.updateEndpointSecret = updateEndpointSecret;
|
|
@@ -232,12 +232,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
232
232
|
trigger = {
|
|
233
233
|
eventTrigger: {
|
|
234
234
|
eventType: gcfFunction.eventTrigger.eventType,
|
|
235
|
-
eventFilters:
|
|
236
|
-
{
|
|
237
|
-
attribute: "resource",
|
|
238
|
-
value: gcfFunction.eventTrigger.resource,
|
|
239
|
-
},
|
|
240
|
-
],
|
|
235
|
+
eventFilters: { resource: gcfFunction.eventTrigger.resource },
|
|
241
236
|
retry: !!((_e = gcfFunction.eventTrigger.failurePolicy) === null || _e === void 0 ? void 0 : _e.retry),
|
|
242
237
|
},
|
|
243
238
|
};
|
|
@@ -254,7 +249,8 @@ function endpointFromFunction(gcfFunction) {
|
|
|
254
249
|
if (securityLevel) {
|
|
255
250
|
endpoint.securityLevel = securityLevel;
|
|
256
251
|
}
|
|
257
|
-
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "
|
|
252
|
+
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "minInstances", "maxInstances", "ingressSettings", "labels", "environmentVariables", "secretEnvironmentVariables", "sourceUploadUrl");
|
|
253
|
+
proto.renameIfPresent(endpoint, gcfFunction, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
258
254
|
if (gcfFunction.vpcConnector) {
|
|
259
255
|
endpoint.vpc = { connector: gcfFunction.vpcConnector };
|
|
260
256
|
proto.renameIfPresent(endpoint.vpc, gcfFunction, "egressSettings", "vpcConnectorEgressSettings");
|
|
@@ -278,13 +274,9 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
278
274
|
};
|
|
279
275
|
proto.copyIfPresent(gcfFunction, endpoint, "labels");
|
|
280
276
|
if (backend.isEventTriggered(endpoint)) {
|
|
281
|
-
const resourceFilter = backend.findEventFilter(endpoint, "resource");
|
|
282
|
-
if (!resourceFilter) {
|
|
283
|
-
throw new error_1.FirebaseError("Invalid event trigger definition. Expected event filter with 'resource' attribute.");
|
|
284
|
-
}
|
|
285
277
|
gcfFunction.eventTrigger = {
|
|
286
278
|
eventType: endpoint.eventTrigger.eventType,
|
|
287
|
-
resource:
|
|
279
|
+
resource: endpoint.eventTrigger.eventFilters.resource,
|
|
288
280
|
};
|
|
289
281
|
gcfFunction.eventTrigger.failurePolicy = endpoint.eventTrigger.retry
|
|
290
282
|
? { retry: {} }
|
|
@@ -311,7 +303,8 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
311
303
|
gcfFunction.httpsTrigger.securityLevel = endpoint.securityLevel;
|
|
312
304
|
}
|
|
313
305
|
}
|
|
314
|
-
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "
|
|
306
|
+
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "availableMemoryMb", "minInstances", "maxInstances", "ingressSettings", "environmentVariables", "secretEnvironmentVariables");
|
|
307
|
+
proto.renameIfPresent(gcfFunction, endpoint, "timeout", "timeoutSeconds", proto.durationFromSeconds);
|
|
315
308
|
if (endpoint.vpc) {
|
|
316
309
|
proto.renameIfPresent(gcfFunction, endpoint.vpc, "vpcConnector", "connector");
|
|
317
310
|
proto.renameIfPresent(gcfFunction, endpoint.vpc, "vpcConnectorEgressSettings", "egressSettings");
|
|
@@ -166,9 +166,8 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
166
166
|
serviceConfig: {},
|
|
167
167
|
};
|
|
168
168
|
proto.copyIfPresent(gcfFunction, endpoint, "labels");
|
|
169
|
-
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "serviceAccountEmail", "ingressSettings");
|
|
169
|
+
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "serviceAccountEmail", "ingressSettings", "timeoutSeconds");
|
|
170
170
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemory", "availableMemoryMb", (mb) => `${mb}M`);
|
|
171
|
-
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
172
171
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "minInstanceCount", "minInstances");
|
|
173
172
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "maxInstanceCount", "maxInstances");
|
|
174
173
|
if (endpoint.vpc) {
|
|
@@ -180,23 +179,19 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
180
179
|
eventType: endpoint.eventTrigger.eventType,
|
|
181
180
|
};
|
|
182
181
|
if (gcfFunction.eventTrigger.eventType === v2_1.PUBSUB_PUBLISH_EVENT) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
gcfFunction.eventTrigger.pubsubTopic = pubsubFilter.value;
|
|
188
|
-
for (const filter of endpoint.eventTrigger.eventFilters) {
|
|
189
|
-
if (filter.attribute === "topic") {
|
|
182
|
+
gcfFunction.eventTrigger.pubsubTopic = endpoint.eventTrigger.eventFilters.topic;
|
|
183
|
+
gcfFunction.eventTrigger.eventFilters = [];
|
|
184
|
+
for (const [attribute, value] of Object.entries(endpoint.eventTrigger.eventFilters)) {
|
|
185
|
+
if (attribute === "topic")
|
|
190
186
|
continue;
|
|
191
|
-
}
|
|
192
|
-
if (!gcfFunction.eventTrigger.eventFilters) {
|
|
193
|
-
gcfFunction.eventTrigger.eventFilters = [];
|
|
194
|
-
}
|
|
195
|
-
gcfFunction.eventTrigger.eventFilters.push(filter);
|
|
187
|
+
gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
|
|
196
188
|
}
|
|
197
189
|
}
|
|
198
190
|
else {
|
|
199
|
-
gcfFunction.eventTrigger.eventFilters =
|
|
191
|
+
gcfFunction.eventTrigger.eventFilters = [];
|
|
192
|
+
for (const [attribute, value] of Object.entries(endpoint.eventTrigger.eventFilters)) {
|
|
193
|
+
gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
|
|
194
|
+
}
|
|
200
195
|
}
|
|
201
196
|
proto.renameIfPresent(gcfFunction.eventTrigger, endpoint.eventTrigger, "triggerRegion", "region");
|
|
202
197
|
if (endpoint.eventTrigger.retry) {
|
|
@@ -239,19 +234,16 @@ function endpointFromFunction(gcfFunction) {
|
|
|
239
234
|
trigger = {
|
|
240
235
|
eventTrigger: {
|
|
241
236
|
eventType: gcfFunction.eventTrigger.eventType,
|
|
242
|
-
eventFilters:
|
|
237
|
+
eventFilters: {},
|
|
243
238
|
retry: false,
|
|
244
239
|
},
|
|
245
240
|
};
|
|
246
241
|
if (gcfFunction.eventTrigger.pubsubTopic) {
|
|
247
|
-
trigger.eventTrigger.eventFilters.
|
|
248
|
-
attribute: "topic",
|
|
249
|
-
value: gcfFunction.eventTrigger.pubsubTopic,
|
|
250
|
-
});
|
|
242
|
+
trigger.eventTrigger.eventFilters.topic = gcfFunction.eventTrigger.pubsubTopic;
|
|
251
243
|
}
|
|
252
244
|
else {
|
|
253
245
|
for (const { attribute, value } of gcfFunction.eventTrigger.eventFilters || []) {
|
|
254
|
-
trigger.eventTrigger.eventFilters
|
|
246
|
+
trigger.eventTrigger.eventFilters[attribute] = value;
|
|
255
247
|
}
|
|
256
248
|
}
|
|
257
249
|
proto.renameIfPresent(trigger.eventTrigger, gcfFunction.eventTrigger, "region", "triggerRegion");
|
|
@@ -265,9 +257,8 @@ function endpointFromFunction(gcfFunction) {
|
|
|
265
257
|
const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
|
|
266
258
|
project,
|
|
267
259
|
region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, uri: gcfFunction.serviceConfig.uri });
|
|
268
|
-
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "ingressSettings", "environmentVariables");
|
|
260
|
+
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "ingressSettings", "environmentVariables", "timeoutSeconds");
|
|
269
261
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "availableMemoryMb", "availableMemory", megabytes);
|
|
270
|
-
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
|
|
271
262
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
|
|
272
263
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
|
|
273
264
|
proto.copyIfPresent(endpoint, gcfFunction, "labels");
|
package/lib/gcp/cloudtasks.js
CHANGED
|
@@ -13,7 +13,6 @@ const client = new apiv2_1.Client({
|
|
|
13
13
|
exports.DEFAULT_SETTINGS = {
|
|
14
14
|
rateLimits: {
|
|
15
15
|
maxConcurrentDispatches: 1000,
|
|
16
|
-
maxBurstSize: 100,
|
|
17
16
|
maxDispatchesPerSecond: 500,
|
|
18
17
|
},
|
|
19
18
|
state: "RUNNING",
|
|
@@ -133,10 +132,13 @@ exports.queueNameForEndpoint = queueNameForEndpoint;
|
|
|
133
132
|
function queueFromEndpoint(endpoint) {
|
|
134
133
|
const queue = Object.assign(Object.assign({}, JSON.parse(JSON.stringify(exports.DEFAULT_SETTINGS))), { name: queueNameForEndpoint(endpoint) });
|
|
135
134
|
if (endpoint.taskQueueTrigger.rateLimits) {
|
|
136
|
-
proto.copyIfPresent(queue.rateLimits, endpoint.taskQueueTrigger.rateLimits, "
|
|
135
|
+
proto.copyIfPresent(queue.rateLimits, endpoint.taskQueueTrigger.rateLimits, "maxConcurrentDispatches", "maxDispatchesPerSecond");
|
|
137
136
|
}
|
|
138
137
|
if (endpoint.taskQueueTrigger.retryConfig) {
|
|
139
|
-
proto.copyIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxAttempts", "
|
|
138
|
+
proto.copyIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxAttempts", "maxDoublings");
|
|
139
|
+
proto.renameIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxRetryDuration", "maxRetrySeconds", proto.durationFromSeconds);
|
|
140
|
+
proto.renameIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxBackoff", "maxBackoffSeconds", proto.durationFromSeconds);
|
|
141
|
+
proto.renameIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "minBackoff", "minBackoffSeconds", proto.durationFromSeconds);
|
|
140
142
|
}
|
|
141
143
|
return queue;
|
|
142
144
|
}
|
package/lib/gcp/secretManager.js
CHANGED
|
@@ -133,7 +133,7 @@ async function createSecret(projectId, name, labels) {
|
|
|
133
133
|
},
|
|
134
134
|
labels,
|
|
135
135
|
}, { queryParams: { secretId: name } });
|
|
136
|
-
return parseSecretResourceName(createRes.body.name);
|
|
136
|
+
return Object.assign(Object.assign({}, parseSecretResourceName(createRes.body.name)), { labels });
|
|
137
137
|
}
|
|
138
138
|
exports.createSecret = createSecret;
|
|
139
139
|
async function patchSecret(projectId, name, labels) {
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
3
|
+
exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const url = require("url");
|
|
6
6
|
const clc = require("cli-color");
|
|
@@ -406,3 +406,32 @@ function groupBy(arr, f) {
|
|
|
406
406
|
}, {});
|
|
407
407
|
}
|
|
408
408
|
exports.groupBy = groupBy;
|
|
409
|
+
function cloneArray(arr) {
|
|
410
|
+
return arr.map((e) => cloneDeep(e));
|
|
411
|
+
}
|
|
412
|
+
function cloneObject(obj) {
|
|
413
|
+
const clone = {};
|
|
414
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
415
|
+
clone[k] = cloneDeep(v);
|
|
416
|
+
}
|
|
417
|
+
return clone;
|
|
418
|
+
}
|
|
419
|
+
function cloneDeep(obj) {
|
|
420
|
+
if (typeof obj !== "object" || !obj) {
|
|
421
|
+
return obj;
|
|
422
|
+
}
|
|
423
|
+
if (obj instanceof RegExp) {
|
|
424
|
+
return RegExp(obj, obj.flags);
|
|
425
|
+
}
|
|
426
|
+
if (obj instanceof Date) {
|
|
427
|
+
return new Date(obj);
|
|
428
|
+
}
|
|
429
|
+
if (Array.isArray(obj)) {
|
|
430
|
+
return cloneArray(obj);
|
|
431
|
+
}
|
|
432
|
+
if (obj instanceof Map) {
|
|
433
|
+
return new Map(obj.entries());
|
|
434
|
+
}
|
|
435
|
+
return cloneObject(obj);
|
|
436
|
+
}
|
|
437
|
+
exports.cloneDeep = cloneDeep;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-tools",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.6.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "firebase-tools",
|
|
9
|
-
"version": "10.
|
|
9
|
+
"version": "10.6.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@google-cloud/pubsub": "^2.18.4",
|