firebase-tools 9.23.0 → 10.0.1
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/api.js +0 -1
- package/lib/commands/database-remove.js +2 -2
- package/lib/commands/database-set.js +2 -2
- package/lib/commands/database-update.js +2 -2
- package/lib/commands/firestore-delete.js +2 -2
- package/lib/commands/functions-delete.js +7 -1
- package/lib/commands/hosting-disable.js +3 -3
- package/lib/commands/remoteconfig-get.js +6 -5
- package/lib/deploy/functions/checkIam.js +65 -4
- package/lib/deploy/functions/containerCleaner.js +28 -38
- package/lib/deploy/functions/deploy.js +6 -7
- package/lib/deploy/functions/eventTypes.js +10 -0
- package/lib/deploy/functions/prepare.js +12 -2
- package/lib/deploy/functions/release/fabricator.js +6 -1
- package/lib/deploy/functions/release/index.js +6 -2
- package/lib/deploy/functions/release/reporter.js +4 -0
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +1 -1
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +3 -9
- package/lib/deploy/functions/services/index.js +38 -0
- package/lib/deploy/functions/services/storage.js +43 -0
- package/lib/deploy/functions/triggerRegionHelper.js +6 -30
- package/lib/emulator/auth/handlers.js +1 -1
- package/lib/emulator/auth/operations.js +27 -9
- package/lib/emulator/auth/widget_ui.js +17 -3
- package/lib/emulator/downloadableEmulators.js +5 -5
- package/lib/emulator/functionsEmulator.js +15 -1
- package/lib/emulator/functionsEmulatorRuntime.js +1 -1
- package/lib/emulator/functionsEmulatorShared.js +1 -0
- package/lib/emulator/pubsubEmulator.js +58 -45
- package/lib/emulator/storage/cloudFunctions.js +13 -6
- package/lib/ensureApiEnabled.js +11 -14
- package/lib/extensions/askUserForParam.js +32 -8
- package/lib/extensions/emulator/triggerHelper.js +1 -0
- package/lib/functions/env.js +2 -2
- package/lib/gcp/cloudfunctions.js +11 -2
- package/lib/gcp/cloudfunctionsv2.js +35 -3
- package/lib/gcp/docker.js +29 -1
- package/lib/gcp/location.js +44 -0
- package/lib/gcp/storage.js +48 -32
- package/lib/init/features/functions/index.js +3 -3
- package/lib/init/features/hosting/github.js +3 -0
- package/lib/init/features/project.js +2 -1
- package/lib/previews.js +1 -1
- package/package.json +3 -3
- package/templates/init/functions/javascript/package.lint.json +1 -1
- package/templates/init/functions/javascript/package.nolint.json +1 -1
- package/templates/init/functions/typescript/package.lint.json +1 -1
- package/templates/init/functions/typescript/package.nolint.json +1 -1
- package/CHANGELOG.md +0 -1
|
@@ -77,6 +77,7 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
|
|
|
77
77
|
"You may only select one option.",
|
|
78
78
|
choices: utils_1.convertExtensionOptionToLabeledList(paramSpec.options),
|
|
79
79
|
});
|
|
80
|
+
valid = checkResponse(response, paramSpec);
|
|
80
81
|
break;
|
|
81
82
|
case extensionsApi_1.ParamType.MULTISELECT:
|
|
82
83
|
response = await utils_1.onceWithJoin({
|
|
@@ -95,11 +96,13 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
|
|
|
95
96
|
"You may select multiple options.",
|
|
96
97
|
choices: utils_1.convertExtensionOptionToLabeledList(paramSpec.options),
|
|
97
98
|
});
|
|
99
|
+
valid = checkResponse(response, paramSpec);
|
|
98
100
|
break;
|
|
99
101
|
case extensionsApi_1.ParamType.SECRET:
|
|
100
102
|
response = reconfiguring
|
|
101
103
|
? await promptReconfigureSecret(projectId, instanceId, paramSpec)
|
|
102
104
|
: await promptCreateSecret(projectId, instanceId, paramSpec);
|
|
105
|
+
valid = true;
|
|
103
106
|
break;
|
|
104
107
|
default:
|
|
105
108
|
response = await prompt_1.promptOnce({
|
|
@@ -108,8 +111,8 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
|
|
|
108
111
|
default: paramSpec.default,
|
|
109
112
|
message: `Enter a value for ${label}:`,
|
|
110
113
|
});
|
|
114
|
+
valid = checkResponse(response, paramSpec);
|
|
111
115
|
}
|
|
112
|
-
valid = checkResponse(response, paramSpec);
|
|
113
116
|
}
|
|
114
117
|
return response;
|
|
115
118
|
}
|
|
@@ -139,10 +142,24 @@ async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
|
|
|
139
142
|
type: "password",
|
|
140
143
|
message: `This secret will be stored in Cloud Secret Manager as ${secretName}.\nEnter new value for ${paramSpec.label.trim()}:`,
|
|
141
144
|
});
|
|
142
|
-
if (
|
|
143
|
-
|
|
145
|
+
if (secretValue === "" && paramSpec.required) {
|
|
146
|
+
logger_1.logger.info(`Secret value cannot be empty for required param ${paramSpec.param}`);
|
|
147
|
+
return promptReconfigureSecret(projectId, instanceId, paramSpec);
|
|
148
|
+
}
|
|
149
|
+
else if (secretValue !== "") {
|
|
150
|
+
if (checkResponse(secretValue, paramSpec)) {
|
|
151
|
+
if (!secret) {
|
|
152
|
+
secret = await secretManagerApi.createSecret(projectId, secretName, secretsUtils.getSecretLabels(instanceId));
|
|
153
|
+
}
|
|
154
|
+
return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
return promptReconfigureSecret(projectId, instanceId, paramSpec);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return "";
|
|
144
162
|
}
|
|
145
|
-
return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
|
|
146
163
|
case SecretUpdateAction.LEAVE:
|
|
147
164
|
default:
|
|
148
165
|
return paramSpec.default || "";
|
|
@@ -158,13 +175,20 @@ async function promptCreateSecret(projectId, instanceId, paramSpec, secretName)
|
|
|
158
175
|
});
|
|
159
176
|
if (secretValue === "" && paramSpec.required) {
|
|
160
177
|
logger_1.logger.info(`Secret value cannot be empty for required param ${paramSpec.param}`);
|
|
161
|
-
return
|
|
178
|
+
return promptCreateSecret(projectId, instanceId, paramSpec, name);
|
|
162
179
|
}
|
|
163
180
|
else if (secretValue !== "") {
|
|
164
|
-
|
|
165
|
-
|
|
181
|
+
if (checkResponse(secretValue, paramSpec)) {
|
|
182
|
+
const secret = await secretManagerApi.createSecret(projectId, name, secretsUtils.getSecretLabels(instanceId));
|
|
183
|
+
return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
return promptCreateSecret(projectId, instanceId, paramSpec, name);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
return "";
|
|
166
191
|
}
|
|
167
|
-
return secretValue;
|
|
168
192
|
}
|
|
169
193
|
exports.promptCreateSecret = promptCreateSecret;
|
|
170
194
|
async function generateSecretName(projectId, instanceId, paramName) {
|
package/lib/functions/env.js
CHANGED
|
@@ -32,11 +32,11 @@ const RESERVED_KEYS = [
|
|
|
32
32
|
const LINE_RE = new RegExp("^" +
|
|
33
33
|
"\\s*" +
|
|
34
34
|
"(\\w+)" +
|
|
35
|
-
"\\s
|
|
35
|
+
"\\s*=[\\f\\t\\v]*" +
|
|
36
36
|
"(" +
|
|
37
37
|
"\\s*'(?:\\\\'|[^'])*'|" +
|
|
38
38
|
'\\s*"(?:\\\\"|[^"])*"|' +
|
|
39
|
-
"[^#\\r\\n]
|
|
39
|
+
"[^#\\r\\n]*" +
|
|
40
40
|
")?" +
|
|
41
41
|
"\\s*" +
|
|
42
42
|
"(?:#[^\\n]*)?" +
|
|
@@ -4,6 +4,7 @@ exports.functionFromEndpoint = exports.endpointFromFunction = exports.listAllFun
|
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
7
|
+
const previews_1 = require("../previews");
|
|
7
8
|
const api = require("../api");
|
|
8
9
|
const backend = require("../deploy/functions/backend");
|
|
9
10
|
const utils = require("../utils");
|
|
@@ -50,8 +51,12 @@ async function createFunction(cloudFunction) {
|
|
|
50
51
|
const apiPath = cloudFunction.name.substring(0, cloudFunction.name.lastIndexOf("/"));
|
|
51
52
|
const endpoint = `/${exports.API_VERSION}/${apiPath}`;
|
|
52
53
|
try {
|
|
54
|
+
const headers = {};
|
|
55
|
+
if (previews_1.previews.artifactregistry) {
|
|
56
|
+
headers["X-Firebase-Artifact-Registry"] = "optin";
|
|
57
|
+
}
|
|
53
58
|
const res = await api.request("POST", endpoint, {
|
|
54
|
-
headers
|
|
59
|
+
headers,
|
|
55
60
|
auth: true,
|
|
56
61
|
data: cloudFunction,
|
|
57
62
|
origin: api.functionsOrigin,
|
|
@@ -146,8 +151,12 @@ async function updateFunction(cloudFunction) {
|
|
|
146
151
|
const endpoint = `/${exports.API_VERSION}/${cloudFunction.name}`;
|
|
147
152
|
const fieldMasks = proto.fieldMasks(cloudFunction, "labels", "environmentVariables");
|
|
148
153
|
try {
|
|
154
|
+
const headers = {};
|
|
155
|
+
if (previews_1.previews.artifactregistry) {
|
|
156
|
+
headers["X-Firebase-Artifact-Registry"] = "optin";
|
|
157
|
+
}
|
|
149
158
|
const res = await api.request("PATCH", endpoint, {
|
|
150
|
-
headers
|
|
159
|
+
headers,
|
|
151
160
|
qs: {
|
|
152
161
|
updateMask: fieldMasks.join(","),
|
|
153
162
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.PUBSUB_PUBLISH_EVENT = exports.API_VERSION = void 0;
|
|
3
|
+
exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.megabytes = exports.PUBSUB_PUBLISH_EVENT = exports.API_VERSION = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const apiv2_1 = require("../apiv2");
|
|
6
6
|
const error_1 = require("../error");
|
|
@@ -17,6 +17,35 @@ const client = new apiv2_1.Client({
|
|
|
17
17
|
apiVersion: exports.API_VERSION,
|
|
18
18
|
});
|
|
19
19
|
exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
|
|
20
|
+
const BYTES_PER_UNIT = {
|
|
21
|
+
"": 1,
|
|
22
|
+
k: 1e3,
|
|
23
|
+
M: 1e6,
|
|
24
|
+
G: 1e9,
|
|
25
|
+
T: 1e12,
|
|
26
|
+
Ki: 1 << 10,
|
|
27
|
+
Mi: 1 << 20,
|
|
28
|
+
Gi: 1 << 30,
|
|
29
|
+
Ti: 1 << 40,
|
|
30
|
+
};
|
|
31
|
+
function megabytes(memory) {
|
|
32
|
+
const re = /^([0-9]+(\.[0-9]*)?)(Ki|Mi|Gi|Ti|k|M|G|T|([eE]([0-9]+)))?$/;
|
|
33
|
+
const matches = re.exec(memory);
|
|
34
|
+
if (!matches) {
|
|
35
|
+
throw new Error(`Invalid memory quantity "${memory}""`);
|
|
36
|
+
}
|
|
37
|
+
const quantity = Number.parseFloat(matches[1]);
|
|
38
|
+
let bytes;
|
|
39
|
+
if (matches[5]) {
|
|
40
|
+
bytes = quantity * Math.pow(10, Number.parseFloat(matches[5]));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const suffix = matches[3] || "";
|
|
44
|
+
bytes = quantity * BYTES_PER_UNIT[suffix];
|
|
45
|
+
}
|
|
46
|
+
return bytes / 1e6;
|
|
47
|
+
}
|
|
48
|
+
exports.megabytes = megabytes;
|
|
20
49
|
function functionsOpLogReject(funcName, type, err) {
|
|
21
50
|
var _a, _b;
|
|
22
51
|
if (((_b = (_a = err === null || err === void 0 ? void 0 : err.context) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode) === 429) {
|
|
@@ -136,7 +165,8 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
136
165
|
serviceConfig: {},
|
|
137
166
|
};
|
|
138
167
|
proto.copyIfPresent(gcfFunction, endpoint, "labels");
|
|
139
|
-
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "
|
|
168
|
+
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "vpcConnector", "vpcConnectorEgressSettings", "serviceAccountEmail", "ingressSettings");
|
|
169
|
+
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemory", "availableMemoryMb", (mb) => `${mb}M`);
|
|
140
170
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
141
171
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "minInstanceCount", "minInstances");
|
|
142
172
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "maxInstanceCount", "maxInstances");
|
|
@@ -153,6 +183,7 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
153
183
|
gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
|
|
154
184
|
}
|
|
155
185
|
}
|
|
186
|
+
proto.renameIfPresent(gcfFunction.eventTrigger, endpoint.eventTrigger, "triggerRegion", "region");
|
|
156
187
|
if (endpoint.eventTrigger.retry) {
|
|
157
188
|
logger_1.logger.warn("Cannot set a retry policy on Cloud Function", endpoint.id);
|
|
158
189
|
}
|
|
@@ -207,7 +238,8 @@ function endpointFromFunction(gcfFunction) {
|
|
|
207
238
|
const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
|
|
208
239
|
project,
|
|
209
240
|
region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, uri: gcfFunction.serviceConfig.uri });
|
|
210
|
-
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "
|
|
241
|
+
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
|
|
242
|
+
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "availableMemoryMb", "availableMemory", megabytes);
|
|
211
243
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
|
|
212
244
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
|
|
213
245
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
|
package/lib/gcp/docker.js
CHANGED
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Client = void 0;
|
|
3
|
+
exports.Client = exports.GCR_SUBDOMAIN_MAPPING = void 0;
|
|
4
4
|
const error_1 = require("../error");
|
|
5
5
|
const api = require("../apiv2");
|
|
6
|
+
exports.GCR_SUBDOMAIN_MAPPING = {
|
|
7
|
+
"us-west1": "us",
|
|
8
|
+
"us-west2": "us",
|
|
9
|
+
"us-west3": "us",
|
|
10
|
+
"us-west4": "us",
|
|
11
|
+
"us-central1": "us",
|
|
12
|
+
"us-central2": "us",
|
|
13
|
+
"us-east1": "us",
|
|
14
|
+
"us-east4": "us",
|
|
15
|
+
"northamerica-northeast1": "us",
|
|
16
|
+
"southamerica-east1": "us",
|
|
17
|
+
"europe-west1": "eu",
|
|
18
|
+
"europe-west2": "eu",
|
|
19
|
+
"europe-west3": "eu",
|
|
20
|
+
"europe-west4": "eu",
|
|
21
|
+
"europe-west5": "eu",
|
|
22
|
+
"europe-west6": "eu",
|
|
23
|
+
"europe-central2": "eu",
|
|
24
|
+
"europe-north1": "eu",
|
|
25
|
+
"asia-east1": "asia",
|
|
26
|
+
"asia-east2": "asia",
|
|
27
|
+
"asia-northeast1": "asia",
|
|
28
|
+
"asia-northeast2": "asia",
|
|
29
|
+
"asia-northeast3": "asia",
|
|
30
|
+
"asia-south1": "asia",
|
|
31
|
+
"asia-southeast2": "asia",
|
|
32
|
+
"australia-southeast1": "asia",
|
|
33
|
+
};
|
|
6
34
|
function isErrors(response) {
|
|
7
35
|
return !!response && Object.prototype.hasOwnProperty.call(response, "errors");
|
|
8
36
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.regionInLocation = exports.DUAL_REGION_MAPPING = exports.MULTI_REGION_MAPPING = void 0;
|
|
4
|
+
exports.MULTI_REGION_MAPPING = {
|
|
5
|
+
"us-central1": "us",
|
|
6
|
+
"us-east1": "us",
|
|
7
|
+
"us-east4": "us",
|
|
8
|
+
"us-west1": "us",
|
|
9
|
+
"us-west2": "us",
|
|
10
|
+
"us-west3": "us",
|
|
11
|
+
"us-west4": "us",
|
|
12
|
+
"europe-central2": "eu",
|
|
13
|
+
"europe-north1": "eu",
|
|
14
|
+
"europe-west1": "eu",
|
|
15
|
+
"europe-west3": "eu",
|
|
16
|
+
"europe-west4": "eu",
|
|
17
|
+
"europe-west5": "eu",
|
|
18
|
+
"asia-east1": "asia",
|
|
19
|
+
"asia-east2": "asia",
|
|
20
|
+
"asia-northeast1": "asia",
|
|
21
|
+
"asia-northeast2": "asia",
|
|
22
|
+
"asia-northeast3": "asia",
|
|
23
|
+
"asia-south1": "asia",
|
|
24
|
+
"asia-south2": "asia",
|
|
25
|
+
"asia-southeast1": "asia",
|
|
26
|
+
"asia-southeast2": "asia",
|
|
27
|
+
};
|
|
28
|
+
exports.DUAL_REGION_MAPPING = {
|
|
29
|
+
"asia-northeast1": "asia1",
|
|
30
|
+
"asia-northeast2": "asia1",
|
|
31
|
+
"europe-north1": "eur4",
|
|
32
|
+
"europe-west4": "eur4",
|
|
33
|
+
"us-central1": "nam4",
|
|
34
|
+
"us-east1": "nam4",
|
|
35
|
+
};
|
|
36
|
+
function regionInLocation(region, location) {
|
|
37
|
+
region = region.toLowerCase();
|
|
38
|
+
location = location.toLowerCase();
|
|
39
|
+
if (exports.MULTI_REGION_MAPPING[region] === location || exports.DUAL_REGION_MAPPING[region] === location) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
exports.regionInLocation = regionInLocation;
|
package/lib/gcp/storage.js
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getServiceAccount = exports.getBucket = exports.deleteObject = exports.uploadObject = exports.upload = exports.getDefaultBucket = void 0;
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const api = require("../api");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const error_1 = require("../error");
|
|
8
|
+
async function getDefaultBucket(projectId) {
|
|
9
|
+
try {
|
|
10
|
+
const resp = await api.request("GET", "/v1/apps/" + projectId, {
|
|
11
|
+
auth: true,
|
|
12
|
+
origin: api.appengineOrigin,
|
|
13
|
+
});
|
|
13
14
|
if (resp.body.defaultBucket === "undefined") {
|
|
14
|
-
logger.debug("Default storage bucket is undefined.");
|
|
15
|
-
|
|
15
|
+
logger_1.logger.debug("Default storage bucket is undefined.");
|
|
16
|
+
throw new error_1.FirebaseError("Your project is being set up. Please wait a minute before deploying again.");
|
|
16
17
|
}
|
|
17
|
-
return
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
return resp.body.defaultBucket;
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
logger_1.logger.info("\n\nThere was an issue deploying your functions. Verify that your project has a Google App Engine instance setup at https://console.cloud.google.com/appengine and try again. If this issue persists, please contact support.");
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
exports.getDefaultBucket = getDefaultBucket;
|
|
26
|
+
async function upload(source, uploadUrl, extraHeaders) {
|
|
24
27
|
const url = new URL(uploadUrl);
|
|
25
28
|
const result = await api.request("PUT", url.pathname + url.search, {
|
|
26
29
|
data: source.stream,
|
|
@@ -33,9 +36,10 @@ async function _uploadSource(source, uploadUrl, extraHeaders) {
|
|
|
33
36
|
generation: result.response.headers["x-goog-generation"],
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
|
-
|
|
39
|
+
exports.upload = upload;
|
|
40
|
+
async function uploadObject(source, bucketName) {
|
|
37
41
|
if (path.extname(source.file) !== ".zip") {
|
|
38
|
-
throw new FirebaseError(`Expected a file name ending in .zip, got ${source.file}`);
|
|
42
|
+
throw new error_1.FirebaseError(`Expected a file name ending in .zip, got ${source.file}`);
|
|
39
43
|
}
|
|
40
44
|
const location = `/${bucketName}/${path.basename(source.file)}`;
|
|
41
45
|
const result = await api.request("PUT", location, {
|
|
@@ -55,13 +59,15 @@ async function _uploadObject(source, bucketName) {
|
|
|
55
59
|
generation: result.response.headers["x-goog-generation"],
|
|
56
60
|
};
|
|
57
61
|
}
|
|
58
|
-
|
|
62
|
+
exports.uploadObject = uploadObject;
|
|
63
|
+
function deleteObject(location) {
|
|
59
64
|
return api.request("DELETE", location, {
|
|
60
65
|
auth: true,
|
|
61
66
|
origin: api.storageOrigin,
|
|
62
67
|
});
|
|
63
68
|
}
|
|
64
|
-
|
|
69
|
+
exports.deleteObject = deleteObject;
|
|
70
|
+
async function getBucket(bucketName) {
|
|
65
71
|
try {
|
|
66
72
|
const result = await api.request("GET", `/storage/v1/b/${bucketName}`, {
|
|
67
73
|
auth: true,
|
|
@@ -70,16 +76,26 @@ async function _getBucket(bucketName) {
|
|
|
70
76
|
return result.body;
|
|
71
77
|
}
|
|
72
78
|
catch (err) {
|
|
73
|
-
logger.debug(err);
|
|
74
|
-
throw new FirebaseError("Failed to obtain the storage bucket", {
|
|
79
|
+
logger_1.logger.debug(err);
|
|
80
|
+
throw new error_1.FirebaseError("Failed to obtain the storage bucket", {
|
|
81
|
+
original: err,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.getBucket = getBucket;
|
|
86
|
+
async function getServiceAccount(projectId) {
|
|
87
|
+
try {
|
|
88
|
+
const response = await api.request("GET", `/storage/v1/projects/${projectId}/serviceAccount`, {
|
|
89
|
+
auth: true,
|
|
90
|
+
origin: api.storageOrigin,
|
|
91
|
+
});
|
|
92
|
+
return response.body;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
logger_1.logger.debug(err);
|
|
96
|
+
throw new error_1.FirebaseError("Failed to obtain the Cloud Storage service agent", {
|
|
75
97
|
original: err,
|
|
76
98
|
});
|
|
77
99
|
}
|
|
78
100
|
}
|
|
79
|
-
|
|
80
|
-
getDefaultBucket: _getDefaultBucket,
|
|
81
|
-
deleteObject: _deleteObject,
|
|
82
|
-
upload: _uploadSource,
|
|
83
|
-
uploadObject: _uploadObject,
|
|
84
|
-
getBucket: _getBucket,
|
|
85
|
-
};
|
|
101
|
+
exports.getServiceAccount = getServiceAccount;
|
|
@@ -5,7 +5,7 @@ const logger_1 = require("../../../logger");
|
|
|
5
5
|
const prompt_1 = require("../../../prompt");
|
|
6
6
|
const requirePermissions_1 = require("../../../requirePermissions");
|
|
7
7
|
const previews_1 = require("../../../previews");
|
|
8
|
-
const
|
|
8
|
+
const ensureApiEnabled_1 = require("../../../ensureApiEnabled");
|
|
9
9
|
module.exports = async function (setup, config, options) {
|
|
10
10
|
var _a, _b;
|
|
11
11
|
logger_1.logger.info();
|
|
@@ -17,8 +17,8 @@ module.exports = async function (setup, config, options) {
|
|
|
17
17
|
if (projectId) {
|
|
18
18
|
await requirePermissions_1.requirePermissions(Object.assign(Object.assign({}, options), { project: projectId }));
|
|
19
19
|
await Promise.all([
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
ensureApiEnabled_1.ensure(projectId, "cloudfunctions.googleapis.com", "unused", true),
|
|
21
|
+
ensureApiEnabled_1.ensure(projectId, "runtimeconfig.googleapis.com", "unused", true),
|
|
22
22
|
]);
|
|
23
23
|
}
|
|
24
24
|
const choices = [
|
|
@@ -31,6 +31,9 @@ async function initGitHub(setup, config, options) {
|
|
|
31
31
|
if (!setup.projectId) {
|
|
32
32
|
return utils_1.reject("Could not determine Project ID, can't set up GitHub workflow.", { exit: 1 });
|
|
33
33
|
}
|
|
34
|
+
if (!setup.config.hosting) {
|
|
35
|
+
return utils_1.reject(`Didn't find a Hosting config in firebase.json. Run ${cli_color_1.bold("firebase init hosting")} instead.`);
|
|
36
|
+
}
|
|
34
37
|
logger_1.logger.info();
|
|
35
38
|
const gitRoot = getGitFolderPath();
|
|
36
39
|
GIT_DIR = path.join(gitRoot, ".git");
|
|
@@ -72,7 +72,7 @@ async function doSetup(setup, config, options) {
|
|
|
72
72
|
logger_1.logger.info(`but for now we'll just set up a default project.`);
|
|
73
73
|
logger_1.logger.info();
|
|
74
74
|
const projectFromRcFile = _.get(setup.rcfile, "projects.default");
|
|
75
|
-
if (projectFromRcFile) {
|
|
75
|
+
if (projectFromRcFile && !options.project) {
|
|
76
76
|
utils.logBullet(`.firebaserc already has a default project, using ${projectFromRcFile}.`);
|
|
77
77
|
const rcProject = await projects_1.getFirebaseProject(projectFromRcFile);
|
|
78
78
|
setup.projectId = rcProject.projectId;
|
|
@@ -81,6 +81,7 @@ async function doSetup(setup, config, options) {
|
|
|
81
81
|
}
|
|
82
82
|
let projectMetaData;
|
|
83
83
|
if (options.project) {
|
|
84
|
+
logger_1.logger.debug(`Using project from CLI flag: ${options.project}`);
|
|
84
85
|
projectMetaData = await projects_1.getFirebaseProject(options.project);
|
|
85
86
|
}
|
|
86
87
|
else {
|
package/lib/previews.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.previews = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const configstore_1 = require("./configstore");
|
|
6
|
-
exports.previews = Object.assign({ rtdbrules: false, ext: false, extdev: false, rtdbmanagement: false, functionsv2: false, golang: false, deletegcfartifacts: false, dotenv: false }, configstore_1.configstore.get("previews"));
|
|
6
|
+
exports.previews = Object.assign({ rtdbrules: false, ext: false, extdev: false, rtdbmanagement: false, functionsv2: false, golang: false, deletegcfartifacts: false, dotenv: false, artifactregistry: false }, configstore_1.configstore.get("previews"));
|
|
7
7
|
if (process.env.FIREBASE_CLI_PREVIEWS) {
|
|
8
8
|
process.env.FIREBASE_CLI_PREVIEWS.split(",").forEach((feature) => {
|
|
9
9
|
if (lodash_1.has(exports.previews, feature)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-tools",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.1",
|
|
4
4
|
"description": "Command-Line Interface for Firebase",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
],
|
|
56
56
|
"preferGlobal": true,
|
|
57
57
|
"engines": {
|
|
58
|
-
"node": ">=
|
|
58
|
+
"node": ">= 12"
|
|
59
59
|
},
|
|
60
60
|
"author": "Firebase (https://firebase.google.com/)",
|
|
61
61
|
"license": "MIT",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"chokidar": "^3.0.2",
|
|
95
95
|
"cjson": "^0.3.1",
|
|
96
96
|
"cli-color": "^1.2.0",
|
|
97
|
-
"cli-table": "
|
|
97
|
+
"cli-table": "0.3.11",
|
|
98
98
|
"commander": "^4.0.1",
|
|
99
99
|
"configstore": "^5.0.1",
|
|
100
100
|
"cors": "^2.8.5",
|
package/CHANGELOG.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
- `firebase deploy --only extensions` now supports project specifc .env files. When deploying to multiple projects, param values that are different between projects can be put in `extensions/${extensionInstanceId}.env.${projectIdOrAlias}` and common param values can be put in `extensions/${extensionInstanceId}.env`.
|