firebase-tools 10.1.3 → 10.2.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 +1 -0
- package/lib/apiv2.js +4 -0
- package/lib/auth.js +62 -25
- package/lib/commands/auth-import.js +1 -1
- package/lib/commands/ext-configure.js +1 -0
- 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-config-clone.js +1 -1
- 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/deploy/functions/backend.js +9 -1
- package/lib/deploy/functions/ensure.js +112 -0
- package/lib/deploy/functions/ensureCloudBuildEnabled.js +0 -49
- package/lib/deploy/functions/prepare.js +12 -18
- 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 +56 -1
- package/lib/deploy/hosting/client.js +9 -0
- package/lib/deploy/hosting/convertConfig.js +6 -0
- package/lib/deploy/hosting/index.js +5 -5
- package/lib/deploy/hosting/prepare.js +25 -25
- package/lib/deploy/hosting/release.js +21 -24
- package/lib/emulator/commandUtils.js +5 -1
- package/lib/emulator/controller.js +3 -1
- package/lib/emulator/downloadableEmulators.js +29 -12
- package/lib/emulator/emulatorLogger.js +7 -0
- package/lib/emulator/functionsEmulator.js +122 -80
- 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/extensionsHelper.js +10 -17
- package/lib/extensions/listExtensions.js +2 -0
- 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/cloudfunctions.js +2 -2
- package/lib/gcp/secretManager.js +128 -46
- package/lib/gcp/storage.js +5 -3
- package/lib/hosting/functionsProxy.js +15 -5
- package/lib/previews.js +1 -1
- package/lib/responseToError.js +16 -7
- package/lib/serve/functions.js +2 -2
- package/lib/serve/hosting.js +1 -1
- package/lib/utils.js +6 -1
- package/npm-shrinkwrap.json +124 -45
- package/package.json +4 -4
- package/schema/firebase-config.json +27 -0
|
@@ -2,20 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.inferDetailsFromExisting = exports.prepare = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
|
-
const ensureCloudBuildEnabled_1 = require("./ensureCloudBuildEnabled");
|
|
6
|
-
const functionsDeployHelper_1 = require("./functionsDeployHelper");
|
|
7
|
-
const utils_1 = require("../../utils");
|
|
8
|
-
const prepareFunctionsUpload_1 = require("./prepareFunctionsUpload");
|
|
9
|
-
const prompts_1 = require("./prompts");
|
|
10
5
|
const backend = require("./backend");
|
|
11
6
|
const ensureApiEnabled = require("../../ensureApiEnabled");
|
|
12
7
|
const functionsConfig = require("../../functionsConfig");
|
|
13
8
|
const functionsEnv = require("../../functions/env");
|
|
14
|
-
const previews_1 = require("../../previews");
|
|
15
|
-
const projectUtils_1 = require("../../projectUtils");
|
|
16
|
-
const track_1 = require("../../track");
|
|
17
9
|
const runtimes = require("./runtimes");
|
|
18
10
|
const validate = require("./validate");
|
|
11
|
+
const ensure = require("./ensure");
|
|
12
|
+
const functionsDeployHelper_1 = require("./functionsDeployHelper");
|
|
13
|
+
const utils_1 = require("../../utils");
|
|
14
|
+
const prepareFunctionsUpload_1 = require("./prepareFunctionsUpload");
|
|
15
|
+
const prompts_1 = require("./prompts");
|
|
16
|
+
const projectUtils_1 = require("../../projectUtils");
|
|
17
|
+
const track_1 = require("../../track");
|
|
19
18
|
const logger_1 = require("../../logger");
|
|
20
19
|
const triggerRegionHelper_1 = require("./triggerRegionHelper");
|
|
21
20
|
const checkIam_1 = require("./checkIam");
|
|
@@ -24,14 +23,7 @@ function hasUserConfig(config) {
|
|
|
24
23
|
return Object.keys(config).length > 1;
|
|
25
24
|
}
|
|
26
25
|
function hasDotenv(opts) {
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
async function maybeEnableAR(projectId) {
|
|
30
|
-
if (!previews_1.previews.artifactregistry) {
|
|
31
|
-
return ensureApiEnabled.check(projectId, "artifactregistry.googleapis.com", "functions", true);
|
|
32
|
-
}
|
|
33
|
-
await ensureApiEnabled.ensure(projectId, "artifactregistry.googleapis.com", "functions");
|
|
34
|
-
return true;
|
|
26
|
+
return functionsEnv.hasUserEnvs(opts);
|
|
35
27
|
}
|
|
36
28
|
async function prepare(context, options, payload) {
|
|
37
29
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
@@ -54,8 +46,8 @@ async function prepare(context, options, payload) {
|
|
|
54
46
|
const checkAPIsEnabled = await Promise.all([
|
|
55
47
|
ensureApiEnabled.ensure(projectId, "cloudfunctions.googleapis.com", "functions"),
|
|
56
48
|
ensureApiEnabled.check(projectId, "runtimeconfig.googleapis.com", "runtimeconfig", true),
|
|
57
|
-
|
|
58
|
-
maybeEnableAR(projectId),
|
|
49
|
+
ensure.cloudBuildEnabled(projectId),
|
|
50
|
+
ensure.maybeEnableAR(projectId),
|
|
59
51
|
]);
|
|
60
52
|
context.runtimeConfigEnabled = checkAPIsEnabled[1];
|
|
61
53
|
context.artifactRegistryEnabled = checkAPIsEnabled[3];
|
|
@@ -125,6 +117,8 @@ async function prepare(context, options, payload) {
|
|
|
125
117
|
await (0, prompts_1.promptForFailurePolicies)(options, matchingBackend, haveBackend);
|
|
126
118
|
await (0, prompts_1.promptForMinInstances)(options, matchingBackend, haveBackend);
|
|
127
119
|
await backend.checkAvailability(context, wantBackend);
|
|
120
|
+
await validate.secretsAreValid(projectId, matchingBackend);
|
|
121
|
+
await ensure.secretAccess(projectId, matchingBackend, haveBackend);
|
|
128
122
|
}
|
|
129
123
|
exports.prepare = prepare;
|
|
130
124
|
function inferDetailsFromExisting(want, have, usedDotenv) {
|
|
@@ -56,6 +56,7 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
56
56
|
labels: "object",
|
|
57
57
|
ingressSettings: "string",
|
|
58
58
|
environmentVariables: "object",
|
|
59
|
+
secretEnvironmentVariables: "array",
|
|
59
60
|
httpsTrigger: "object",
|
|
60
61
|
eventTrigger: "object",
|
|
61
62
|
scheduleTrigger: "object",
|
|
@@ -107,6 +107,18 @@ function addResourcesToBackend(projectId, runtime, annotation, want) {
|
|
|
107
107
|
}
|
|
108
108
|
endpoint.vpcConnector = maybeId;
|
|
109
109
|
}
|
|
110
|
+
if (annotation.secrets) {
|
|
111
|
+
const secretEnvs = [];
|
|
112
|
+
for (const secret of annotation.secrets) {
|
|
113
|
+
const secretEnv = {
|
|
114
|
+
secret,
|
|
115
|
+
projectId,
|
|
116
|
+
key: secret,
|
|
117
|
+
};
|
|
118
|
+
secretEnvs.push(secretEnv);
|
|
119
|
+
}
|
|
120
|
+
endpoint.secretEnvironmentVariables = secretEnvs;
|
|
121
|
+
}
|
|
110
122
|
proto.copyIfPresent(endpoint, annotation, "concurrency", "serviceAccountEmail", "labels", "vpcConnectorEgressSettings", "ingressSettings", "timeout", "maxInstances", "minInstances", "availableMemoryMb");
|
|
111
123
|
want.endpoints[region] = want.endpoints[region] || {};
|
|
112
124
|
want.endpoints[region][endpoint.id] = endpoint;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.functionIdsAreValid = exports.functionsDirectoryExists = exports.endpointsAreValid = void 0;
|
|
3
|
+
exports.secretsAreValid = exports.functionIdsAreValid = exports.functionsDirectoryExists = exports.endpointsAreValid = void 0;
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const clc = require("cli-color");
|
|
6
6
|
const error_1 = require("../../error");
|
|
7
|
+
const secretManager_1 = require("../../gcp/secretManager");
|
|
8
|
+
const logger_1 = require("../../logger");
|
|
7
9
|
const fsutils = require("../../fsutils");
|
|
8
10
|
const backend = require("./backend");
|
|
11
|
+
const utils = require("../../utils");
|
|
12
|
+
const secrets = require("../../functions/secrets");
|
|
9
13
|
function endpointsAreValid(wantBackend) {
|
|
10
14
|
functionIdsAreValid(backend.allEndpoints(wantBackend));
|
|
11
15
|
const gcfV1WithConcurrency = backend
|
|
@@ -62,3 +66,54 @@ function functionIdsAreValid(functions) {
|
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
exports.functionIdsAreValid = functionIdsAreValid;
|
|
69
|
+
async function secretsAreValid(projectId, wantBackend) {
|
|
70
|
+
const endpoints = backend
|
|
71
|
+
.allEndpoints(wantBackend)
|
|
72
|
+
.filter((e) => e.secretEnvironmentVariables && e.secretEnvironmentVariables.length > 0);
|
|
73
|
+
validatePlatformTargets(endpoints);
|
|
74
|
+
await validateSecretVersions(projectId, endpoints);
|
|
75
|
+
}
|
|
76
|
+
exports.secretsAreValid = secretsAreValid;
|
|
77
|
+
function validatePlatformTargets(endpoints) {
|
|
78
|
+
const supportedPlatforms = ["gcfv1"];
|
|
79
|
+
const unsupported = endpoints.filter((e) => !supportedPlatforms.includes(e.platform));
|
|
80
|
+
if (unsupported.length > 0) {
|
|
81
|
+
const errs = unsupported.map((e) => `${e.id}[platform=${e.platform}]`);
|
|
82
|
+
throw new error_1.FirebaseError(`Tried to set secret environment variables on ${errs.join(", ")}. ` +
|
|
83
|
+
`Only ${supportedPlatforms.join(", ")} support secret environments.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function validateSecretVersions(projectId, endpoints) {
|
|
87
|
+
const toResolve = new Set();
|
|
88
|
+
for (const s of secrets.of(endpoints)) {
|
|
89
|
+
toResolve.add(s.secret);
|
|
90
|
+
}
|
|
91
|
+
const results = await utils.allSettled(Array.from(toResolve).map(async (secret) => {
|
|
92
|
+
const sv = await (0, secretManager_1.getSecretVersion)(projectId, secret, "latest");
|
|
93
|
+
logger_1.logger.debug(`Resolved secret version of ${clc.bold(secret)} to ${clc.bold(sv.versionId)}.`);
|
|
94
|
+
return sv;
|
|
95
|
+
}));
|
|
96
|
+
const secretVersions = {};
|
|
97
|
+
const errs = [];
|
|
98
|
+
for (const result of results) {
|
|
99
|
+
if (result.status === "fulfilled") {
|
|
100
|
+
const sv = result.value;
|
|
101
|
+
if (sv.state != "ENABLED") {
|
|
102
|
+
errs.push(new error_1.FirebaseError(`Expected secret ${sv.secret.name}@${sv.versionId} to be in state ENABLED not ${sv.state}.`));
|
|
103
|
+
}
|
|
104
|
+
secretVersions[sv.secret.name] = sv;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
errs.push(new error_1.FirebaseError(result.reason.message));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (errs.length) {
|
|
111
|
+
throw new error_1.FirebaseError("Failed to validate secret versions", { children: errs });
|
|
112
|
+
}
|
|
113
|
+
for (const s of secrets.of(endpoints)) {
|
|
114
|
+
s.version = secretVersions[s.secret].versionId;
|
|
115
|
+
if (!s.version) {
|
|
116
|
+
throw new error_1.FirebaseError("Secret version is unexpectedly undefined. This should never happen.");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.client = void 0;
|
|
4
|
+
const api_1 = require("../../api");
|
|
5
|
+
const apiv2_1 = require("../../apiv2");
|
|
6
|
+
exports.client = new apiv2_1.Client({
|
|
7
|
+
urlPrefix: api_1.hostingApiOrigin,
|
|
8
|
+
apiVersion: "v1beta1",
|
|
9
|
+
});
|
|
@@ -46,6 +46,12 @@ function convertConfig(config) {
|
|
|
46
46
|
}
|
|
47
47
|
else if ("function" in rewrite) {
|
|
48
48
|
vRewrite.function = rewrite.function;
|
|
49
|
+
if (rewrite.region) {
|
|
50
|
+
vRewrite.functionRegion = rewrite.region;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
vRewrite.functionRegion = "us-central1";
|
|
54
|
+
}
|
|
49
55
|
}
|
|
50
56
|
else if ("dynamicLinks" in rewrite) {
|
|
51
57
|
vRewrite.dynamicLinks = rewrite.dynamicLinks;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.release = exports.deploy = exports.prepare = void 0;
|
|
4
|
-
|
|
5
|
-
exports
|
|
6
|
-
|
|
4
|
+
var prepare_1 = require("./prepare");
|
|
5
|
+
Object.defineProperty(exports, "prepare", { enumerable: true, get: function () { return prepare_1.prepare; } });
|
|
6
|
+
var deploy_1 = require("./deploy");
|
|
7
7
|
Object.defineProperty(exports, "deploy", { enumerable: true, get: function () { return deploy_1.deploy; } });
|
|
8
|
-
|
|
9
|
-
exports
|
|
8
|
+
var release_1 = require("./release");
|
|
9
|
+
Object.defineProperty(exports, "release", { enumerable: true, get: function () { return release_1.release; } });
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.prepare = void 0;
|
|
4
|
+
const error_1 = require("../../error");
|
|
5
|
+
const client_1 = require("./client");
|
|
6
|
+
const projectUtils_1 = require("../../projectUtils");
|
|
7
|
+
const normalizedHostingConfigs_1 = require("../../hosting/normalizedHostingConfigs");
|
|
8
|
+
const validate_1 = require("./validate");
|
|
9
|
+
const convertConfig_1 = require("./convertConfig");
|
|
5
10
|
const deploymentTool = require("../../deploymentTool");
|
|
6
|
-
|
|
7
|
-
const { normalizedHostingConfigs } = require("../../hosting/normalizedHostingConfigs");
|
|
8
|
-
const { validateDeploy } = require("./validate");
|
|
9
|
-
module.exports = function (context, options) {
|
|
11
|
+
async function prepare(context, options) {
|
|
10
12
|
if (options.public) {
|
|
11
|
-
if (
|
|
12
|
-
throw new FirebaseError("Cannot specify --public option with multi-site configuration.");
|
|
13
|
+
if (Array.isArray(options.config.get("hosting"))) {
|
|
14
|
+
throw new error_1.FirebaseError("Cannot specify --public option with multi-site configuration.");
|
|
13
15
|
}
|
|
14
16
|
options.config.set("hosting.public", options.public);
|
|
15
17
|
}
|
|
16
|
-
const
|
|
18
|
+
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
19
|
+
const configs = (0, normalizedHostingConfigs_1.normalizedHostingConfigs)(options, { resolveTargets: true });
|
|
17
20
|
if (configs.length === 0) {
|
|
18
21
|
return Promise.resolve();
|
|
19
22
|
}
|
|
20
23
|
context.hosting = {
|
|
21
|
-
deploys: configs.map(
|
|
24
|
+
deploys: configs.map((cfg) => {
|
|
22
25
|
return { config: cfg, site: cfg.site };
|
|
23
26
|
}),
|
|
24
27
|
};
|
|
25
28
|
const versionCreates = [];
|
|
26
|
-
|
|
29
|
+
for (const deploy of context.hosting.deploys) {
|
|
27
30
|
const cfg = deploy.config;
|
|
28
|
-
validateDeploy(deploy, options);
|
|
31
|
+
(0, validate_1.validateDeploy)(deploy, options);
|
|
29
32
|
const data = {
|
|
30
|
-
config: convertConfig(cfg),
|
|
33
|
+
config: (0, convertConfig_1.convertConfig)(cfg),
|
|
31
34
|
labels: deploymentTool.labels(),
|
|
32
35
|
};
|
|
33
|
-
versionCreates.push(
|
|
34
|
-
.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
data,
|
|
38
|
-
})
|
|
39
|
-
.then(function (result) {
|
|
40
|
-
deploy.version = result.body.name;
|
|
36
|
+
versionCreates.push(client_1.client
|
|
37
|
+
.post(`/projects/${projectNumber}/sites/${deploy.site}/versions`, data)
|
|
38
|
+
.then((res) => {
|
|
39
|
+
deploy.version = res.body.name;
|
|
41
40
|
}));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
}
|
|
41
|
+
}
|
|
42
|
+
await Promise.all(versionCreates);
|
|
43
|
+
}
|
|
44
|
+
exports.prepare = prepare;
|
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.release = void 0;
|
|
4
|
+
const client_1 = require("./client");
|
|
5
|
+
const logger_1 = require("../../logger");
|
|
6
|
+
const projectUtils_1 = require("../../projectUtils");
|
|
3
7
|
const utils = require("../../utils");
|
|
4
|
-
|
|
5
|
-
module.exports = function (context, options) {
|
|
8
|
+
async function release(context, options) {
|
|
6
9
|
if (!context.hosting || !context.hosting.deploys) {
|
|
7
|
-
return
|
|
10
|
+
return;
|
|
8
11
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
});
|
|
17
|
-
logger.debug("[hosting] finalized version for " + deploy.site + ":", finalizeResult.body);
|
|
18
|
-
utils.logLabeledSuccess("hosting[" + deploy.site + "]", "version finalized");
|
|
19
|
-
utils.logLabeledBullet("hosting[" + deploy.site + "]", "releasing new version...");
|
|
12
|
+
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
13
|
+
logger_1.logger.debug(JSON.stringify(context.hosting.deploys, null, 2));
|
|
14
|
+
await Promise.all(context.hosting.deploys.map(async (deploy) => {
|
|
15
|
+
utils.logLabeledBullet(`hosting[${deploy.site}]`, "finalizing version...");
|
|
16
|
+
const finalizeResult = await client_1.client.patch(`/${deploy.version}`, { status: "FINALIZED" }, { queryParams: { updateMask: "status" } });
|
|
17
|
+
logger_1.logger.debug(`[hosting] finalized version for ${deploy.site}:${finalizeResult.body}`);
|
|
18
|
+
utils.logLabeledSuccess(`hosting[${deploy.site}]`, "version finalized");
|
|
19
|
+
utils.logLabeledBullet(`hosting[${deploy.site}]`, "releasing new version...");
|
|
20
20
|
const channelSegment = context.hostingChannel && context.hostingChannel !== "live"
|
|
21
21
|
? `/channels/${context.hostingChannel}`
|
|
22
22
|
: "";
|
|
23
23
|
if (channelSegment) {
|
|
24
|
-
logger.debug("[hosting] releasing to channel:", context.hostingChannel);
|
|
24
|
+
logger_1.logger.debug("[hosting] releasing to channel:", context.hostingChannel);
|
|
25
25
|
}
|
|
26
|
-
const releaseResult = await
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
data: { message: options.message || null },
|
|
30
|
-
});
|
|
31
|
-
logger.debug("[hosting] release:", releaseResult.body);
|
|
32
|
-
utils.logLabeledSuccess("hosting[" + deploy.site + "]", "release complete");
|
|
26
|
+
const releaseResult = await client_1.client.post(`/projects/${projectNumber}/sites/${deploy.site}${channelSegment}/releases`, { message: options.message || null }, { queryParams: { versionName: deploy.version } });
|
|
27
|
+
logger_1.logger.debug("[hosting] release:", releaseResult.body);
|
|
28
|
+
utils.logLabeledSuccess(`hosting[${deploy.site}]`, "release complete");
|
|
33
29
|
}));
|
|
34
|
-
}
|
|
30
|
+
}
|
|
31
|
+
exports.release = release;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
|
|
3
|
+
exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_CWD_DANGER = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const childProcess = require("child_process");
|
|
6
6
|
const controller = require("../emulator/controller");
|
|
@@ -36,6 +36,7 @@ exports.DESC_EXPORT_ON_EXIT = "automatically export emulator data (emulators:exp
|
|
|
36
36
|
`when no dir is provided the location of ${exports.FLAG_IMPORT} is used`;
|
|
37
37
|
exports.EXPORT_ON_EXIT_USAGE_ERROR = `"${exports.FLAG_EXPORT_ON_EXIT_NAME}" must be used with "${exports.FLAG_IMPORT}"` +
|
|
38
38
|
` or provide a dir directly to "${exports.FLAG_EXPORT_ON_EXIT}"`;
|
|
39
|
+
exports.EXPORT_ON_EXIT_CWD_DANGER = `"${exports.FLAG_EXPORT_ON_EXIT_NAME}" must not point to the current directory or parents. Please choose a new/dedicated directory for exports.`;
|
|
39
40
|
exports.FLAG_UI = "--ui";
|
|
40
41
|
exports.DESC_UI = "run the Emulator UI";
|
|
41
42
|
exports.FLAG_TEST_CONFIG = "--test-config <firebase.json file>";
|
|
@@ -131,6 +132,9 @@ function setExportOnExitOptions(options) {
|
|
|
131
132
|
if (options.exportOnExit === true || !options.exportOnExit) {
|
|
132
133
|
throw new error_1.FirebaseError(exports.EXPORT_ON_EXIT_USAGE_ERROR);
|
|
133
134
|
}
|
|
135
|
+
if (path.resolve(".").startsWith(path.resolve(options.exportOnExit))) {
|
|
136
|
+
throw new error_1.FirebaseError(exports.EXPORT_ON_EXIT_CWD_DANGER);
|
|
137
|
+
}
|
|
134
138
|
}
|
|
135
139
|
return;
|
|
136
140
|
}
|
|
@@ -246,7 +246,8 @@ async function startAll(options, showUI = true) {
|
|
|
246
246
|
utils.assertDefined(options.config.src.functions);
|
|
247
247
|
utils.assertDefined(options.config.src.functions.source, "Error: 'functions.source' is not defined");
|
|
248
248
|
utils.assertIsStringOrUndefined(options.extensionDir);
|
|
249
|
-
const
|
|
249
|
+
const projectDir = options.extensionDir || options.config.projectDir;
|
|
250
|
+
const functionsDir = path.join(projectDir, options.config.src.functions.source);
|
|
250
251
|
let inspectFunctions;
|
|
251
252
|
if (options.inspectFunctions) {
|
|
252
253
|
inspectFunctions = commandUtils.parseInspectionPort(options);
|
|
@@ -269,6 +270,7 @@ async function startAll(options, showUI = true) {
|
|
|
269
270
|
];
|
|
270
271
|
const functionsEmulator = new functionsEmulator_1.FunctionsEmulator({
|
|
271
272
|
projectId,
|
|
273
|
+
projectDir,
|
|
272
274
|
emulatableBackends,
|
|
273
275
|
account,
|
|
274
276
|
host: functionsAddr.host,
|
|
@@ -13,6 +13,7 @@ const path = require("path");
|
|
|
13
13
|
const os = require("os");
|
|
14
14
|
const registry_1 = require("./registry");
|
|
15
15
|
const download_1 = require("../emulator/download");
|
|
16
|
+
const previews_1 = require("../previews");
|
|
16
17
|
const EMULATOR_INSTANCE_KILL_TIMEOUT = 4000;
|
|
17
18
|
const CACHE_DIR = process.env.FIREBASE_EMULATORS_PATH || path.join(os.homedir(), ".cache", "firebase", "emulators");
|
|
18
19
|
exports.DownloadDetails = {
|
|
@@ -49,19 +50,35 @@ exports.DownloadDetails = {
|
|
|
49
50
|
namePrefix: "cloud-storage-rules-emulator",
|
|
50
51
|
},
|
|
51
52
|
},
|
|
52
|
-
ui:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
ui: previews_1.previews.emulatoruisnapshot
|
|
54
|
+
? {
|
|
55
|
+
version: "SNAPSHOT",
|
|
56
|
+
downloadPath: path.join(CACHE_DIR, "ui-vSNAPSHOT.zip"),
|
|
57
|
+
unzipDir: path.join(CACHE_DIR, "ui-vSNAPSHOT"),
|
|
58
|
+
binaryPath: path.join(CACHE_DIR, "ui-vSNAPSHOT", "server.bundle.js"),
|
|
59
|
+
opts: {
|
|
60
|
+
cacheDir: CACHE_DIR,
|
|
61
|
+
remoteUrl: "https://storage.googleapis.com/firebase-preview-drop/emulator/ui-vSNAPSHOT.zip",
|
|
62
|
+
expectedSize: -1,
|
|
63
|
+
expectedChecksum: "",
|
|
64
|
+
skipCache: true,
|
|
65
|
+
skipChecksumAndSize: true,
|
|
66
|
+
namePrefix: "ui",
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
: {
|
|
70
|
+
version: "1.6.5",
|
|
71
|
+
downloadPath: path.join(CACHE_DIR, "ui-v1.6.5.zip"),
|
|
72
|
+
unzipDir: path.join(CACHE_DIR, "ui-v1.6.5"),
|
|
73
|
+
binaryPath: path.join(CACHE_DIR, "ui-v1.6.5", "server.bundle.js"),
|
|
74
|
+
opts: {
|
|
75
|
+
cacheDir: CACHE_DIR,
|
|
76
|
+
remoteUrl: "https://storage.googleapis.com/firebase-preview-drop/emulator/ui-v1.6.5.zip",
|
|
77
|
+
expectedSize: 3816994,
|
|
78
|
+
expectedChecksum: "92dfff4b2ef8ab616e8a60cc93e0a00b",
|
|
79
|
+
namePrefix: "ui",
|
|
80
|
+
},
|
|
63
81
|
},
|
|
64
|
-
},
|
|
65
82
|
pubsub: {
|
|
66
83
|
downloadPath: path.join(CACHE_DIR, "pubsub-emulator-0.1.0.zip"),
|
|
67
84
|
version: "0.1.0",
|
|
@@ -13,6 +13,7 @@ const TYPE_VERBOSITY = {
|
|
|
13
13
|
USER: 2,
|
|
14
14
|
WARN: 2,
|
|
15
15
|
WARN_ONCE: 2,
|
|
16
|
+
ERROR: 2,
|
|
16
17
|
};
|
|
17
18
|
var Verbosity;
|
|
18
19
|
(function (Verbosity) {
|
|
@@ -79,6 +80,9 @@ class EmulatorLogger {
|
|
|
79
80
|
case "SUCCESS":
|
|
80
81
|
utils.logSuccess(text, "info", mergedData);
|
|
81
82
|
break;
|
|
83
|
+
case "ERROR":
|
|
84
|
+
utils.logBullet(text, "error", mergedData);
|
|
85
|
+
break;
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
handleRuntimeLog(log, ignore = []) {
|
|
@@ -196,6 +200,9 @@ You can probably fix this by running "npm install ${systemLog.data.name}@latest"
|
|
|
196
200
|
EmulatorLogger.warnOnceCache.add(text);
|
|
197
201
|
}
|
|
198
202
|
break;
|
|
203
|
+
case "ERROR":
|
|
204
|
+
utils.logLabeledError(label, text, "error", mergedData);
|
|
205
|
+
break;
|
|
199
206
|
}
|
|
200
207
|
}
|
|
201
208
|
static shouldSupress(type) {
|