firebase-tools 10.1.2 → 10.2.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/api.js +1 -0
- package/lib/apiv2.js +92 -48
- package/lib/archiveDirectory.js +63 -73
- package/lib/auth.js +62 -25
- package/lib/commands/ext-configure.js +1 -0
- package/lib/commands/ext-dev-usage.js +3 -8
- package/lib/commands/ext-install.js +1 -0
- package/lib/commands/ext-uninstall.js +1 -0
- package/lib/commands/ext-update.js +1 -0
- package/lib/commands/functions-secrets-access.js +17 -0
- package/lib/commands/functions-secrets-destroy.js +40 -0
- package/lib/commands/functions-secrets-get.js +21 -0
- package/lib/commands/functions-secrets-prune.js +50 -0
- package/lib/commands/functions-secrets-set.js +46 -0
- package/lib/commands/index.js +7 -3
- package/lib/commands/login.js +1 -1
- package/lib/database/metadata.js +16 -24
- package/lib/deploy/functions/backend.js +11 -1
- package/lib/deploy/functions/ensure.js +112 -0
- package/lib/deploy/functions/ensureCloudBuildEnabled.js +0 -49
- package/lib/deploy/functions/prepare.js +13 -19
- package/lib/deploy/functions/release/fabricator.js +4 -1
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +1 -0
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +12 -0
- package/lib/deploy/functions/validate.js +83 -1
- package/lib/deploy/hosting/convertConfig.js +45 -24
- package/lib/deploy/hosting/prepare.js +1 -1
- package/lib/emulator/controller.js +3 -1
- package/lib/emulator/emulatorLogger.js +7 -0
- package/lib/emulator/functionsEmulator.js +113 -79
- package/lib/emulator/functionsEmulatorRuntime.js +100 -83
- package/lib/emulator/functionsEmulatorShared.js +51 -1
- package/lib/emulator/functionsEmulatorShell.js +1 -2
- package/lib/emulator/functionsRuntimeWorker.js +1 -1
- package/lib/emulator/storage/apis/gcloud.js +2 -2
- package/lib/emulator/storage/files.js +8 -3
- package/lib/extensions/askUserForParam.js +1 -1
- package/lib/extensions/diagnose.js +56 -0
- package/lib/extensions/extensionsApi.js +0 -1
- package/lib/extensions/extensionsHelper.js +10 -17
- package/lib/extensions/resolveSource.js +1 -53
- package/lib/extensions/secretsUtils.js +1 -1
- package/lib/extensions/updateHelper.js +0 -14
- package/lib/extensions/utils.js +4 -2
- package/lib/functions/env.js +5 -7
- package/lib/functions/secrets.js +112 -0
- package/lib/gcp/cloudbilling.js +8 -19
- package/lib/gcp/cloudfunctions.js +24 -48
- package/lib/gcp/cloudlogging.js +8 -11
- package/lib/gcp/cloudmonitoring.js +8 -5
- package/lib/gcp/cloudscheduler.js +7 -18
- package/lib/gcp/firedata.js +5 -4
- package/lib/gcp/firestore.js +5 -5
- package/lib/gcp/iam.js +18 -33
- package/lib/gcp/resourceManager.js +8 -13
- package/lib/gcp/runtimeconfig.js +31 -53
- package/lib/gcp/secretManager.js +137 -77
- package/lib/gcp/storage.js +25 -29
- package/lib/previews.js +1 -1
- package/lib/serve/functions.js +2 -2
- package/lib/utils.js +6 -1
- package/npm-shrinkwrap.json +962 -987
- package/package.json +5 -3
- package/schema/firebase-config.json +387 -12
- package/templates/init/hosting/index.html +1 -1
|
@@ -1,63 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTrustedPublishers = exports.getExtensionRegistry =
|
|
3
|
+
exports.getTrustedPublishers = exports.getExtensionRegistry = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
|
-
const clc = require("cli-color");
|
|
6
|
-
const { marked } = require("marked");
|
|
7
|
-
const error_1 = require("../error");
|
|
8
5
|
const logger_1 = require("../logger");
|
|
9
|
-
const prompt_1 = require("../prompt");
|
|
10
6
|
const apiv2_1 = require("../apiv2");
|
|
11
7
|
const api_1 = require("../api");
|
|
12
8
|
const EXTENSIONS_REGISTRY_ENDPOINT = "/extensions.json";
|
|
13
|
-
async function confirmUpdateWarning(updateWarning) {
|
|
14
|
-
logger_1.logger.info(marked(updateWarning.description));
|
|
15
|
-
if (updateWarning.action) {
|
|
16
|
-
logger_1.logger.info(marked(updateWarning.action));
|
|
17
|
-
}
|
|
18
|
-
const continueUpdate = await (0, prompt_1.promptOnce)({
|
|
19
|
-
type: "confirm",
|
|
20
|
-
message: "Do you wish to continue with this update?",
|
|
21
|
-
default: false,
|
|
22
|
-
});
|
|
23
|
-
if (!continueUpdate) {
|
|
24
|
-
throw new error_1.FirebaseError(`Update cancelled.`, { exit: 2 });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
exports.confirmUpdateWarning = confirmUpdateWarning;
|
|
28
|
-
function resolveSourceUrl(registryEntry, name, version) {
|
|
29
|
-
const targetVersion = getTargetVersion(registryEntry, version);
|
|
30
|
-
const sourceUrl = _.get(registryEntry, ["versions", targetVersion]);
|
|
31
|
-
if (!sourceUrl) {
|
|
32
|
-
throw new error_1.FirebaseError(`Could not find version ${clc.bold(version)} of extension ${clc.bold(name)}.`);
|
|
33
|
-
}
|
|
34
|
-
return sourceUrl;
|
|
35
|
-
}
|
|
36
|
-
exports.resolveSourceUrl = resolveSourceUrl;
|
|
37
|
-
function isOfficialSource(registryEntry, sourceUrl) {
|
|
38
|
-
const versions = _.get(registryEntry, "versions");
|
|
39
|
-
return _.includes(versions, sourceUrl);
|
|
40
|
-
}
|
|
41
|
-
exports.isOfficialSource = isOfficialSource;
|
|
42
|
-
async function resolveRegistryEntry(name) {
|
|
43
|
-
const extensionsRegistry = await getExtensionRegistry();
|
|
44
|
-
const registryEntry = _.get(extensionsRegistry, name);
|
|
45
|
-
if (!registryEntry) {
|
|
46
|
-
throw new error_1.FirebaseError(`Unable to find extension source named ${clc.bold(name)}.`);
|
|
47
|
-
}
|
|
48
|
-
return registryEntry;
|
|
49
|
-
}
|
|
50
|
-
exports.resolveRegistryEntry = resolveRegistryEntry;
|
|
51
|
-
function getTargetVersion(registryEntry, versionOrLabel) {
|
|
52
|
-
const seekVersion = versionOrLabel || "latest";
|
|
53
|
-
const versionFromLabel = _.get(registryEntry, ["labels", seekVersion]);
|
|
54
|
-
return versionFromLabel || seekVersion;
|
|
55
|
-
}
|
|
56
|
-
exports.getTargetVersion = getTargetVersion;
|
|
57
|
-
function getMinRequiredVersion(registryEntry) {
|
|
58
|
-
return _.get(registryEntry, ["labels", "minRequired"]);
|
|
59
|
-
}
|
|
60
|
-
exports.getMinRequiredVersion = getMinRequiredVersion;
|
|
61
9
|
async function getExtensionRegistry(onlyFeatured) {
|
|
62
10
|
const client = new apiv2_1.Client({ urlPrefix: api_1.firebaseExtensionsRegistryOrigin });
|
|
63
11
|
const res = await client.get(EXTENSIONS_REGISTRY_ENDPOINT);
|
|
@@ -22,7 +22,7 @@ async function grantFirexServiceAgentSecretAdminRole(secret) {
|
|
|
22
22
|
const projectNumber = await (0, getProjectNumber_1.getProjectNumber)({ projectId: secret.projectId });
|
|
23
23
|
const firexSaProjectId = utils.envOverride("FIREBASE_EXTENSIONS_SA_PROJECT_ID", "gcp-sa-firebasemods");
|
|
24
24
|
const saEmail = `service-${projectNumber}@${firexSaProjectId}.iam.gserviceaccount.com`;
|
|
25
|
-
return secretManagerApi.
|
|
25
|
+
return secretManagerApi.ensureServiceAgentRole(secret, [saEmail], "roles/secretmanager.admin");
|
|
26
26
|
}
|
|
27
27
|
exports.grantFirexServiceAgentSecretAdminRole = grantFirexServiceAgentSecretAdminRole;
|
|
28
28
|
async function getManagedSecrets(instance) {
|
|
@@ -6,7 +6,6 @@ const semver = require("semver");
|
|
|
6
6
|
const { marked } = require("marked");
|
|
7
7
|
const error_1 = require("../error");
|
|
8
8
|
const logger_1 = require("../logger");
|
|
9
|
-
const resolveSource = require("./resolveSource");
|
|
10
9
|
const extensionsApi = require("./extensionsApi");
|
|
11
10
|
const refs = require("./refs");
|
|
12
11
|
const extensionsHelper_1 = require("./extensionsHelper");
|
|
@@ -123,19 +122,6 @@ async function updateToVersionFromPublisherSource(projectId, instanceId, extVers
|
|
|
123
122
|
catch (err) {
|
|
124
123
|
throw new error_1.FirebaseError(`Could not find source '${clc.bold(extVersionRef)}' because (${clc.bold(version)}) is not a published version. To update, use the latest version of this extension (${clc.bold(extension.latestVersion)}).`);
|
|
125
124
|
}
|
|
126
|
-
let registryEntry;
|
|
127
|
-
try {
|
|
128
|
-
registryEntry = await resolveSource.resolveRegistryEntry(existingSpec.name);
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
logger_1.logger.debug(`Unable to fetch registry.json entry for ${existingSpec.name}`);
|
|
132
|
-
}
|
|
133
|
-
if (registryEntry) {
|
|
134
|
-
const minVer = resolveSource.getMinRequiredVersion(registryEntry);
|
|
135
|
-
if (minVer && semver.gt(minVer, source.spec.version)) {
|
|
136
|
-
throw new error_1.FirebaseError(`The version you are trying to update to (${clc.bold(source.spec.version)}) is less than the minimum version required (${clc.bold(minVer)}) to use this extension.`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
125
|
showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, extVersionRef);
|
|
140
126
|
warningUpdateToOtherSource(extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION);
|
|
141
127
|
const releaseNotes = await changelog.getReleaseNotesForUpdate({
|
package/lib/extensions/utils.js
CHANGED
|
@@ -22,12 +22,14 @@ function convertExtensionOptionToLabeledList(options) {
|
|
|
22
22
|
}
|
|
23
23
|
exports.convertExtensionOptionToLabeledList = convertExtensionOptionToLabeledList;
|
|
24
24
|
function convertOfficialExtensionsToList(officialExts) {
|
|
25
|
-
|
|
25
|
+
const l = _.map(officialExts, (entry, key) => {
|
|
26
26
|
return {
|
|
27
27
|
checked: false,
|
|
28
|
-
value: key
|
|
28
|
+
value: `${entry.publisher}/${key}`,
|
|
29
29
|
};
|
|
30
30
|
});
|
|
31
|
+
l.sort((a, b) => a.value.localeCompare(b.value));
|
|
32
|
+
return l;
|
|
31
33
|
}
|
|
32
34
|
exports.convertOfficialExtensionsToList = convertOfficialExtensionsToList;
|
|
33
35
|
function getRandomString(length) {
|
package/lib/functions/env.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.hasUserEnvs = exports.validateKey = exports.KeyValidationError = exports.parse = void 0;
|
|
3
|
+
exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.hasUserEnvs = exports.parseStrict = exports.validateKey = exports.KeyValidationError = exports.parse = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const error_1 = require("../error");
|
|
8
8
|
const logger_1 = require("../logger");
|
|
9
|
-
const previews_1 = require("../previews");
|
|
10
9
|
const utils_1 = require("../utils");
|
|
11
10
|
const FUNCTIONS_EMULATOR_DOTENV = ".env.local";
|
|
11
|
+
const RESERVED_PREFIXES = ["X_GOOGLE_", "FIREBASE_", "EXT_"];
|
|
12
12
|
const RESERVED_KEYS = [
|
|
13
13
|
"FIREBASE_CONFIG",
|
|
14
14
|
"CLOUD_RUNTIME_CONFIG",
|
|
@@ -87,8 +87,8 @@ function validateKey(key) {
|
|
|
87
87
|
throw new KeyValidationError(key, `Key ${key} must start with an uppercase ASCII letter or underscore` +
|
|
88
88
|
", and then consist of uppercase ASCII letters, digits, and underscores.");
|
|
89
89
|
}
|
|
90
|
-
if (
|
|
91
|
-
throw new KeyValidationError(key, `Key ${key} starts with a reserved prefix (
|
|
90
|
+
if (RESERVED_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
91
|
+
throw new KeyValidationError(key, `Key ${key} starts with a reserved prefix (${RESERVED_PREFIXES.join(" ")})`);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
exports.validateKey = validateKey;
|
|
@@ -117,6 +117,7 @@ function parseStrict(data) {
|
|
|
117
117
|
}
|
|
118
118
|
return envs;
|
|
119
119
|
}
|
|
120
|
+
exports.parseStrict = parseStrict;
|
|
120
121
|
function findEnvfiles(functionsSource, projectId, projectAlias, isEmulator) {
|
|
121
122
|
const files = [".env"];
|
|
122
123
|
if (isEmulator) {
|
|
@@ -139,9 +140,6 @@ function hasUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, })
|
|
|
139
140
|
exports.hasUserEnvs = hasUserEnvs;
|
|
140
141
|
function loadUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, }) {
|
|
141
142
|
var _a;
|
|
142
|
-
if (!previews_1.previews.dotenv) {
|
|
143
|
-
return {};
|
|
144
|
-
}
|
|
145
143
|
const envFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
|
|
146
144
|
if (envFiles.length == 0) {
|
|
147
145
|
return {};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pruneSecrets = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.labels = exports.isFirebaseManaged = void 0;
|
|
4
|
+
const secretManager_1 = require("../gcp/secretManager");
|
|
5
|
+
const error_1 = require("../error");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
const prompt_1 = require("../prompt");
|
|
8
|
+
const env_1 = require("./env");
|
|
9
|
+
const FIREBASE_MANGED = "firebase-managed";
|
|
10
|
+
function isFirebaseManaged(secret) {
|
|
11
|
+
return Object.keys(secret.labels || []).includes(FIREBASE_MANGED);
|
|
12
|
+
}
|
|
13
|
+
exports.isFirebaseManaged = isFirebaseManaged;
|
|
14
|
+
function labels() {
|
|
15
|
+
return { [FIREBASE_MANGED]: "true" };
|
|
16
|
+
}
|
|
17
|
+
exports.labels = labels;
|
|
18
|
+
function toUpperSnakeCase(key) {
|
|
19
|
+
return key
|
|
20
|
+
.replace("-", "_")
|
|
21
|
+
.replace(".", "_")
|
|
22
|
+
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
|
23
|
+
.toUpperCase();
|
|
24
|
+
}
|
|
25
|
+
async function ensureValidKey(key, options) {
|
|
26
|
+
const transformedKey = toUpperSnakeCase(key);
|
|
27
|
+
if (transformedKey !== key) {
|
|
28
|
+
if (options.force) {
|
|
29
|
+
throw new error_1.FirebaseError("Secret key must be in UPPER_SNAKE_CASE.");
|
|
30
|
+
}
|
|
31
|
+
(0, utils_1.logWarning)(`By convention, secret key must be in UPPER_SNAKE_CASE.`);
|
|
32
|
+
const confirm = await (0, prompt_1.promptOnce)({
|
|
33
|
+
name: "updateKey",
|
|
34
|
+
type: "confirm",
|
|
35
|
+
default: true,
|
|
36
|
+
message: `Would you like to use ${transformedKey} as key instead?`,
|
|
37
|
+
}, options);
|
|
38
|
+
if (!confirm) {
|
|
39
|
+
throw new error_1.FirebaseError("Secret key must be in UPPER_SNAKE_CASE.");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
(0, env_1.validateKey)(transformedKey);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
throw new error_1.FirebaseError(`Invalid secret key ${transformedKey}`, { children: [err] });
|
|
47
|
+
}
|
|
48
|
+
return transformedKey;
|
|
49
|
+
}
|
|
50
|
+
exports.ensureValidKey = ensureValidKey;
|
|
51
|
+
async function ensureSecret(projectId, name, options) {
|
|
52
|
+
try {
|
|
53
|
+
const secret = await (0, secretManager_1.getSecret)(projectId, name);
|
|
54
|
+
if (!isFirebaseManaged(secret)) {
|
|
55
|
+
if (!options.force) {
|
|
56
|
+
(0, utils_1.logWarning)("Your secret is not managed by Firebase. " +
|
|
57
|
+
"Firebase managed secrets are automatically pruned to reduce your monthly cost for using Secret Manager. ");
|
|
58
|
+
const confirm = await (0, prompt_1.promptOnce)({
|
|
59
|
+
name: "updateLabels",
|
|
60
|
+
type: "confirm",
|
|
61
|
+
default: true,
|
|
62
|
+
message: `Would you like to have your secret ${secret.name} managed by Firebase?`,
|
|
63
|
+
}, options);
|
|
64
|
+
if (confirm) {
|
|
65
|
+
return (0, secretManager_1.patchSecret)(projectId, secret.name, Object.assign(Object.assign({}, secret.labels), labels()));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return secret;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err.status !== 404) {
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return await (0, secretManager_1.createSecret)(projectId, name, labels());
|
|
77
|
+
}
|
|
78
|
+
exports.ensureSecret = ensureSecret;
|
|
79
|
+
function of(endpoints) {
|
|
80
|
+
return endpoints.reduce((envs, endpoint) => [...envs, ...(endpoint.secretEnvironmentVariables || [])], []);
|
|
81
|
+
}
|
|
82
|
+
exports.of = of;
|
|
83
|
+
async function pruneSecrets(projectInfo, endpoints) {
|
|
84
|
+
const { projectId, projectNumber } = projectInfo;
|
|
85
|
+
const pruneKey = (name, version) => `${name}@${version}`;
|
|
86
|
+
const prunedSecrets = new Set();
|
|
87
|
+
const haveSecrets = await (0, secretManager_1.listSecrets)(projectId, `labels.${FIREBASE_MANGED}=true`);
|
|
88
|
+
for (const secret of haveSecrets) {
|
|
89
|
+
const versions = await (0, secretManager_1.listSecretVersions)(projectId, secret.name, `state: ENABLED`);
|
|
90
|
+
for (const version of versions) {
|
|
91
|
+
prunedSecrets.add(pruneKey(secret.name, version.versionId));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const sevs = of(endpoints).filter((sev) => sev.projectId === projectId || sev.projectId === projectNumber);
|
|
95
|
+
for (const sev of sevs) {
|
|
96
|
+
let name = sev.secret;
|
|
97
|
+
if (name.includes("/")) {
|
|
98
|
+
const secret = (0, secretManager_1.parseSecretResourceName)(name);
|
|
99
|
+
name = secret.name;
|
|
100
|
+
}
|
|
101
|
+
let version = sev.version;
|
|
102
|
+
if (version === "latest") {
|
|
103
|
+
const resolved = await (0, secretManager_1.getSecretVersion)(projectId, name, version);
|
|
104
|
+
version = resolved.versionId;
|
|
105
|
+
}
|
|
106
|
+
prunedSecrets.delete(pruneKey(name, version));
|
|
107
|
+
}
|
|
108
|
+
return Array.from(prunedSecrets)
|
|
109
|
+
.map((key) => key.split("@"))
|
|
110
|
+
.map(([secret, version]) => ({ projectId, version, secret, key: secret }));
|
|
111
|
+
}
|
|
112
|
+
exports.pruneSecrets = pruneSecrets;
|
package/lib/gcp/cloudbilling.js
CHANGED
|
@@ -1,36 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listBillingAccounts = exports.setBillingAccount = exports.checkBillingEnabled = void 0;
|
|
4
|
-
const
|
|
4
|
+
const api_1 = require("../api");
|
|
5
|
+
const apiv2_1 = require("../apiv2");
|
|
5
6
|
const utils = require("../utils");
|
|
6
7
|
const API_VERSION = "v1";
|
|
8
|
+
const client = new apiv2_1.Client({ urlPrefix: api_1.cloudbillingOrigin, apiVersion: API_VERSION });
|
|
7
9
|
async function checkBillingEnabled(projectId) {
|
|
8
|
-
const res = await
|
|
9
|
-
auth: true,
|
|
10
|
-
origin: api.cloudbillingOrigin,
|
|
11
|
-
retryCodes: [500, 503],
|
|
12
|
-
});
|
|
10
|
+
const res = await client.get(utils.endpoint(["projects", projectId, "billingInfo"]), { retryCodes: [500, 503] });
|
|
13
11
|
return res.body.billingEnabled;
|
|
14
12
|
}
|
|
15
13
|
exports.checkBillingEnabled = checkBillingEnabled;
|
|
16
14
|
async function setBillingAccount(projectId, billingAccountName) {
|
|
17
|
-
const res = await
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
retryCodes: [500, 503],
|
|
21
|
-
data: {
|
|
22
|
-
billingAccountName: billingAccountName,
|
|
23
|
-
},
|
|
24
|
-
});
|
|
15
|
+
const res = await client.put(utils.endpoint(["projects", projectId, "billingInfo"]), {
|
|
16
|
+
billingAccountName: billingAccountName,
|
|
17
|
+
}, { retryCodes: [500, 503] });
|
|
25
18
|
return res.body.billingEnabled;
|
|
26
19
|
}
|
|
27
20
|
exports.setBillingAccount = setBillingAccount;
|
|
28
21
|
async function listBillingAccounts() {
|
|
29
|
-
const res = await
|
|
30
|
-
auth: true,
|
|
31
|
-
origin: api.cloudbillingOrigin,
|
|
32
|
-
retryCodes: [500, 503],
|
|
33
|
-
});
|
|
22
|
+
const res = await client.get(utils.endpoint(["billingAccounts"]), { retryCodes: [500, 503] });
|
|
34
23
|
return res.body.billingAccounts || [];
|
|
35
24
|
}
|
|
36
25
|
exports.listBillingAccounts = listBillingAccounts;
|
|
@@ -5,12 +5,14 @@ const clc = require("cli-color");
|
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
7
7
|
const previews_1 = require("../previews");
|
|
8
|
-
const api = require("../api");
|
|
9
8
|
const backend = require("../deploy/functions/backend");
|
|
10
9
|
const utils = require("../utils");
|
|
11
10
|
const proto = require("./proto");
|
|
12
11
|
const runtimes = require("../deploy/functions/runtimes");
|
|
12
|
+
const apiv2_1 = require("../apiv2");
|
|
13
|
+
const api_1 = require("../api");
|
|
13
14
|
exports.API_VERSION = "v1";
|
|
15
|
+
const client = new apiv2_1.Client({ urlPrefix: api_1.functionsOrigin, apiVersion: exports.API_VERSION });
|
|
14
16
|
function validateFunction(func) {
|
|
15
17
|
proto.assertOneOf("Cloud Function", func, "sourceCode", "sourceArchiveUrl", "sourceRepository", "sourceUploadUrl");
|
|
16
18
|
proto.assertOneOf("Cloud Function", func, "trigger", "httpsTrigger", "eventTrigger");
|
|
@@ -30,16 +32,10 @@ function functionsOpLogReject(funcName, type, err) {
|
|
|
30
32
|
}
|
|
31
33
|
async function generateUploadUrl(projectId, location) {
|
|
32
34
|
const parent = "projects/" + projectId + "/locations/" + location;
|
|
33
|
-
const endpoint =
|
|
35
|
+
const endpoint = `/${parent}/functions:generateUploadUrl`;
|
|
34
36
|
try {
|
|
35
|
-
const res = await
|
|
36
|
-
|
|
37
|
-
json: false,
|
|
38
|
-
origin: api.functionsOrigin,
|
|
39
|
-
retryCodes: [503],
|
|
40
|
-
});
|
|
41
|
-
const responseBody = JSON.parse(res.body);
|
|
42
|
-
return responseBody.uploadUrl;
|
|
37
|
+
const res = await client.post(endpoint, {}, { retryCodes: [503] });
|
|
38
|
+
return res.body.uploadUrl;
|
|
43
39
|
}
|
|
44
40
|
catch (err) {
|
|
45
41
|
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.");
|
|
@@ -49,18 +45,13 @@ async function generateUploadUrl(projectId, location) {
|
|
|
49
45
|
exports.generateUploadUrl = generateUploadUrl;
|
|
50
46
|
async function createFunction(cloudFunction) {
|
|
51
47
|
const apiPath = cloudFunction.name.substring(0, cloudFunction.name.lastIndexOf("/"));
|
|
52
|
-
const endpoint = `/${
|
|
48
|
+
const endpoint = `/${apiPath}`;
|
|
53
49
|
try {
|
|
54
50
|
const headers = {};
|
|
55
51
|
if (previews_1.previews.artifactregistry) {
|
|
56
52
|
headers["X-Firebase-Artifact-Registry"] = "optin";
|
|
57
53
|
}
|
|
58
|
-
const res = await
|
|
59
|
-
headers,
|
|
60
|
-
auth: true,
|
|
61
|
-
data: cloudFunction,
|
|
62
|
-
origin: api.functionsOrigin,
|
|
63
|
-
});
|
|
54
|
+
const res = await client.post(endpoint, cloudFunction, { headers });
|
|
64
55
|
return {
|
|
65
56
|
name: res.body.name,
|
|
66
57
|
type: "create",
|
|
@@ -73,15 +64,11 @@ async function createFunction(cloudFunction) {
|
|
|
73
64
|
}
|
|
74
65
|
exports.createFunction = createFunction;
|
|
75
66
|
async function setIamPolicy(options) {
|
|
76
|
-
const endpoint = `/${
|
|
67
|
+
const endpoint = `/${options.name}:setIamPolicy`;
|
|
77
68
|
try {
|
|
78
|
-
await
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
policy: options.policy,
|
|
82
|
-
updateMask: Object.keys(options.policy).join(","),
|
|
83
|
-
},
|
|
84
|
-
origin: api.functionsOrigin,
|
|
69
|
+
await client.post(endpoint, {
|
|
70
|
+
policy: options.policy,
|
|
71
|
+
updateMask: Object.keys(options.policy).join(","),
|
|
85
72
|
});
|
|
86
73
|
}
|
|
87
74
|
catch (err) {
|
|
@@ -92,12 +79,10 @@ async function setIamPolicy(options) {
|
|
|
92
79
|
}
|
|
93
80
|
exports.setIamPolicy = setIamPolicy;
|
|
94
81
|
async function getIamPolicy(fnName) {
|
|
95
|
-
const endpoint = `/${
|
|
82
|
+
const endpoint = `/${fnName}:getIamPolicy`;
|
|
96
83
|
try {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
origin: api.functionsOrigin,
|
|
100
|
-
});
|
|
84
|
+
const res = await client.get(endpoint);
|
|
85
|
+
return res.body;
|
|
101
86
|
}
|
|
102
87
|
catch (err) {
|
|
103
88
|
throw new error_1.FirebaseError(`Failed to get the IAM Policy on the function ${fnName}`, {
|
|
@@ -148,21 +133,18 @@ async function setInvokerUpdate(projectId, fnName, invoker) {
|
|
|
148
133
|
}
|
|
149
134
|
exports.setInvokerUpdate = setInvokerUpdate;
|
|
150
135
|
async function updateFunction(cloudFunction) {
|
|
151
|
-
const endpoint = `/${
|
|
136
|
+
const endpoint = `/${cloudFunction.name}`;
|
|
152
137
|
const fieldMasks = proto.fieldMasks(cloudFunction, "labels", "environmentVariables");
|
|
153
138
|
try {
|
|
154
139
|
const headers = {};
|
|
155
140
|
if (previews_1.previews.artifactregistry) {
|
|
156
141
|
headers["X-Firebase-Artifact-Registry"] = "optin";
|
|
157
142
|
}
|
|
158
|
-
const res = await
|
|
143
|
+
const res = await client.patch(endpoint, cloudFunction, {
|
|
159
144
|
headers,
|
|
160
|
-
|
|
145
|
+
queryParams: {
|
|
161
146
|
updateMask: fieldMasks.join(","),
|
|
162
147
|
},
|
|
163
|
-
auth: true,
|
|
164
|
-
data: cloudFunction,
|
|
165
|
-
origin: api.functionsOrigin,
|
|
166
148
|
});
|
|
167
149
|
return {
|
|
168
150
|
done: false,
|
|
@@ -176,12 +158,9 @@ async function updateFunction(cloudFunction) {
|
|
|
176
158
|
}
|
|
177
159
|
exports.updateFunction = updateFunction;
|
|
178
160
|
async function deleteFunction(name) {
|
|
179
|
-
const endpoint = `/${
|
|
161
|
+
const endpoint = `/${name}`;
|
|
180
162
|
try {
|
|
181
|
-
const res = await
|
|
182
|
-
auth: true,
|
|
183
|
-
origin: api.functionsOrigin,
|
|
184
|
-
});
|
|
163
|
+
const res = await client.delete(endpoint);
|
|
185
164
|
return {
|
|
186
165
|
done: false,
|
|
187
166
|
name: res.body.name,
|
|
@@ -194,12 +173,9 @@ async function deleteFunction(name) {
|
|
|
194
173
|
}
|
|
195
174
|
exports.deleteFunction = deleteFunction;
|
|
196
175
|
async function list(projectId, region) {
|
|
197
|
-
const endpoint = "/
|
|
176
|
+
const endpoint = "/projects/" + projectId + "/locations/" + region + "/functions";
|
|
198
177
|
try {
|
|
199
|
-
const res = await
|
|
200
|
-
auth: true,
|
|
201
|
-
origin: api.functionsOrigin,
|
|
202
|
-
});
|
|
178
|
+
const res = await client.get(endpoint);
|
|
203
179
|
if (res.body.unreachable && res.body.unreachable.length > 0) {
|
|
204
180
|
logger_1.logger.debug(`[functions] unable to reach the following regions: ${res.body.unreachable.join(", ")}`);
|
|
205
181
|
}
|
|
@@ -264,7 +240,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
264
240
|
if (uri) {
|
|
265
241
|
endpoint.uri = uri;
|
|
266
242
|
}
|
|
267
|
-
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "timeout", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "labels", "environmentVariables", "sourceUploadUrl");
|
|
243
|
+
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "timeout", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "labels", "environmentVariables", "secretEnvironmentVariables", "sourceUploadUrl");
|
|
268
244
|
return endpoint;
|
|
269
245
|
}
|
|
270
246
|
exports.endpointFromFunction = endpointFromFunction;
|
|
@@ -307,7 +283,7 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
307
283
|
else {
|
|
308
284
|
gcfFunction.httpsTrigger = {};
|
|
309
285
|
}
|
|
310
|
-
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "timeout", "availableMemoryMb", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
|
|
286
|
+
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "timeout", "availableMemoryMb", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables", "secretEnvironmentVariables");
|
|
311
287
|
return gcfFunction;
|
|
312
288
|
}
|
|
313
289
|
exports.functionFromEndpoint = functionFromEndpoint;
|
package/lib/gcp/cloudlogging.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listEntries = void 0;
|
|
4
|
-
const
|
|
4
|
+
const api_1 = require("../api");
|
|
5
|
+
const apiv2_1 = require("../apiv2");
|
|
5
6
|
const error_1 = require("../error");
|
|
6
7
|
const API_VERSION = "v2";
|
|
7
8
|
async function listEntries(projectId, filter, pageSize, order) {
|
|
8
|
-
const
|
|
9
|
+
const client = new apiv2_1.Client({ urlPrefix: api_1.cloudloggingOrigin, apiVersion: API_VERSION });
|
|
9
10
|
try {
|
|
10
|
-
const result = await
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
orderBy: "timestamp " + order,
|
|
16
|
-
pageSize: pageSize,
|
|
17
|
-
},
|
|
18
|
-
origin: api.cloudloggingOrigin,
|
|
11
|
+
const result = await client.post("/entries:list", {
|
|
12
|
+
resourceNames: [`projects/${projectId}`],
|
|
13
|
+
filter: filter,
|
|
14
|
+
orderBy: `timestamp ${order}`,
|
|
15
|
+
pageSize: pageSize,
|
|
19
16
|
});
|
|
20
17
|
return result.body.entries;
|
|
21
18
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.queryTimeSeries = exports.ValueType = exports.Reducer = exports.MetricKind = exports.Aligner = exports.TimeSeriesView = exports.CLOUD_MONITORING_VERSION = void 0;
|
|
4
|
-
const
|
|
4
|
+
const api_1 = require("../api");
|
|
5
|
+
const apiv2_1 = require("../apiv2");
|
|
5
6
|
const error_1 = require("../error");
|
|
6
7
|
exports.CLOUD_MONITORING_VERSION = "v3";
|
|
7
8
|
var TimeSeriesView;
|
|
@@ -57,11 +58,13 @@ var ValueType;
|
|
|
57
58
|
ValueType["STRING"] = "STRING";
|
|
58
59
|
})(ValueType = exports.ValueType || (exports.ValueType = {}));
|
|
59
60
|
async function queryTimeSeries(query, projectNumber) {
|
|
61
|
+
const client = new apiv2_1.Client({
|
|
62
|
+
urlPrefix: api_1.cloudMonitoringOrigin,
|
|
63
|
+
apiVersion: exports.CLOUD_MONITORING_VERSION,
|
|
64
|
+
});
|
|
60
65
|
try {
|
|
61
|
-
const res = await
|
|
62
|
-
|
|
63
|
-
origin: api.cloudMonitoringOrigin,
|
|
64
|
-
data: query,
|
|
66
|
+
const res = await client.get(`/projects/${projectNumber}/timeSeries/`, {
|
|
67
|
+
queryParams: query,
|
|
65
68
|
});
|
|
66
69
|
return res.body.timeSeries;
|
|
67
70
|
}
|
|
@@ -4,7 +4,8 @@ exports.jobFromEndpoint = exports.createOrReplaceJob = exports.updateJob = expor
|
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
7
|
-
const
|
|
7
|
+
const api_1 = require("../api");
|
|
8
|
+
const apiv2_1 = require("../apiv2");
|
|
8
9
|
const backend = require("../deploy/functions/backend");
|
|
9
10
|
const proto = require("./proto");
|
|
10
11
|
const functional_1 = require("../functional");
|
|
@@ -17,36 +18,24 @@ function assertValidJob(job) {
|
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
exports.assertValidJob = assertValidJob;
|
|
21
|
+
const apiClient = new apiv2_1.Client({ urlPrefix: api_1.cloudschedulerOrigin, apiVersion: VERSION });
|
|
20
22
|
function createJob(job) {
|
|
21
23
|
const strippedName = job.name.substring(0, job.name.lastIndexOf("/"));
|
|
22
|
-
return
|
|
23
|
-
auth: true,
|
|
24
|
-
origin: api.cloudschedulerOrigin,
|
|
25
|
-
data: Object.assign({ timeZone: DEFAULT_TIME_ZONE }, job),
|
|
26
|
-
});
|
|
24
|
+
return apiClient.post(`/${strippedName}`, Object.assign({ timeZone: DEFAULT_TIME_ZONE }, job));
|
|
27
25
|
}
|
|
28
26
|
exports.createJob = createJob;
|
|
29
27
|
function deleteJob(name) {
|
|
30
|
-
return
|
|
31
|
-
auth: true,
|
|
32
|
-
origin: api.cloudschedulerOrigin,
|
|
33
|
-
});
|
|
28
|
+
return apiClient.delete(`/${name}`);
|
|
34
29
|
}
|
|
35
30
|
exports.deleteJob = deleteJob;
|
|
36
31
|
function getJob(name) {
|
|
37
|
-
return
|
|
38
|
-
auth: true,
|
|
39
|
-
origin: api.cloudschedulerOrigin,
|
|
32
|
+
return apiClient.get(`/${name}`, {
|
|
40
33
|
resolveOnHTTPError: true,
|
|
41
34
|
});
|
|
42
35
|
}
|
|
43
36
|
exports.getJob = getJob;
|
|
44
37
|
function updateJob(job) {
|
|
45
|
-
return
|
|
46
|
-
auth: true,
|
|
47
|
-
origin: api.cloudschedulerOrigin,
|
|
48
|
-
data: Object.assign({ timeZone: DEFAULT_TIME_ZONE }, job),
|
|
49
|
-
});
|
|
38
|
+
return apiClient.patch(`/${job.name}`, Object.assign({ timeZone: DEFAULT_TIME_ZONE }, job));
|
|
50
39
|
}
|
|
51
40
|
exports.updateJob = updateJob;
|
|
52
41
|
async function createOrReplaceJob(job) {
|
package/lib/gcp/firedata.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listDatabaseInstances = void 0;
|
|
4
|
-
const
|
|
4
|
+
const api_1 = require("../api");
|
|
5
|
+
const apiv2_1 = require("../apiv2");
|
|
5
6
|
const logger_1 = require("../logger");
|
|
6
7
|
const utils = require("../utils");
|
|
7
8
|
function _handleErrorResponse(response) {
|
|
@@ -14,9 +15,9 @@ function _handleErrorResponse(response) {
|
|
|
14
15
|
});
|
|
15
16
|
}
|
|
16
17
|
async function listDatabaseInstances(projectNumber) {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const client = new apiv2_1.Client({ urlPrefix: api_1.firedataOrigin, apiVersion: "v1" });
|
|
19
|
+
const response = await client.get(`/projects/${projectNumber}/databases`, {
|
|
20
|
+
resolveOnHTTPError: true,
|
|
20
21
|
});
|
|
21
22
|
if (response.status === 200) {
|
|
22
23
|
return response.body.instance;
|
package/lib/gcp/firestore.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.deleteDocuments = exports.deleteDocument = exports.listCollectionIds = void 0;
|
|
4
4
|
const api_1 = require("../api");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const apiv2_1 = require("../apiv2");
|
|
6
|
+
const apiClient = new apiv2_1.Client({
|
|
7
7
|
auth: true,
|
|
8
8
|
apiVersion: "v1",
|
|
9
9
|
urlPrefix: api_1.firestoreOriginOrEmulator,
|
|
@@ -13,13 +13,13 @@ function listCollectionIds(project) {
|
|
|
13
13
|
const data = {
|
|
14
14
|
pageSize: 2147483647,
|
|
15
15
|
};
|
|
16
|
-
return
|
|
16
|
+
return apiClient.post(url, data).then((res) => {
|
|
17
17
|
return res.body.collectionIds || [];
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
exports.listCollectionIds = listCollectionIds;
|
|
21
21
|
async function deleteDocument(doc) {
|
|
22
|
-
return
|
|
22
|
+
return apiClient.delete(doc.name);
|
|
23
23
|
}
|
|
24
24
|
exports.deleteDocument = deleteDocument;
|
|
25
25
|
async function deleteDocuments(project, docs) {
|
|
@@ -28,7 +28,7 @@ async function deleteDocuments(project, docs) {
|
|
|
28
28
|
return { delete: doc.name };
|
|
29
29
|
});
|
|
30
30
|
const data = { writes };
|
|
31
|
-
const res = await
|
|
31
|
+
const res = await apiClient.post(url, data);
|
|
32
32
|
return res.body.writeResults.length;
|
|
33
33
|
}
|
|
34
34
|
exports.deleteDocuments = deleteDocuments;
|