firebase-tools 11.16.0 → 11.17.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/deploy/extensions/planner.js +2 -1
- package/lib/deploy/functions/build.js +3 -0
- package/lib/deploy/functions/deploy.js +5 -2
- package/lib/deploy/functions/release/fabricator.js +2 -2
- package/lib/deploy/functions/release/sourceTokenScraper.js +34 -7
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +2 -1
- package/lib/deploy/lifecycleHooks.js +2 -1
- package/lib/emulator/auth/apiSpec.js +549 -201
- package/lib/emulator/auth/operations.js +4 -2
- package/lib/emulator/auth/server.js +19 -8
- package/lib/emulator/download.js +2 -1
- package/lib/emulator/downloadableEmulators.js +3 -3
- package/lib/emulator/eventarcEmulator.js +2 -1
- package/lib/emulator/eventarcEmulatorUtils.js +60 -0
- package/lib/emulator/extensionsEmulator.js +1 -1
- package/lib/emulator/functionsEmulator.js +13 -5
- package/lib/emulator/storage/apis/firebase.js +7 -27
- package/lib/emulator/storage/apis/gcloud.js +9 -33
- package/lib/emulator/storage/apis/shared.js +43 -0
- package/lib/emulator/storage/rules/config.js +9 -0
- package/lib/emulator/storage/upload.js +2 -2
- package/lib/extensions/extensionsHelper.js +8 -5
- package/lib/utils.js +1 -1
- package/npm-shrinkwrap.json +38 -72
- package/package.json +1 -1
- package/templates/emulators/default_storage.rules +8 -0
- package/templates/init/functions/golang/functions.go +1 -1
- package/templates/init/functions/javascript/index.js +2 -2
- package/templates/init/functions/typescript/index.ts +1 -1
|
@@ -122,12 +122,13 @@ async function want(args) {
|
|
|
122
122
|
exports.want = want;
|
|
123
123
|
async function resolveVersion(ref) {
|
|
124
124
|
const extensionRef = refs.toExtensionRef(ref);
|
|
125
|
-
const versions = await extensionsApi.listExtensionVersions(extensionRef);
|
|
125
|
+
const versions = await extensionsApi.listExtensionVersions(extensionRef, undefined, true);
|
|
126
126
|
if (versions.length === 0) {
|
|
127
127
|
throw new error_1.FirebaseError(`No versions found for ${extensionRef}`);
|
|
128
128
|
}
|
|
129
129
|
if (!ref.version || ref.version === "latest") {
|
|
130
130
|
return versions
|
|
131
|
+
.filter((ev) => ev.spec.version !== undefined)
|
|
131
132
|
.map((ev) => ev.spec.version)
|
|
132
133
|
.sort(semver.compare)
|
|
133
134
|
.pop();
|
|
@@ -160,6 +160,9 @@ function toBackend(build, paramValues) {
|
|
|
160
160
|
const bkEndpoints = [];
|
|
161
161
|
for (const endpointId of Object.keys(build.endpoints)) {
|
|
162
162
|
const bdEndpoint = build.endpoints[endpointId];
|
|
163
|
+
if (r.resolveBoolean(bdEndpoint.omit || false)) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
163
166
|
let regions = bdEndpoint.region;
|
|
164
167
|
if (typeof regions === "undefined") {
|
|
165
168
|
regions = [api.functionsDefaultRegion];
|
|
@@ -80,7 +80,7 @@ async function deploy(context, options, payload) {
|
|
|
80
80
|
await (0, checkIam_1.checkHttpIam)(context, options, payload);
|
|
81
81
|
const uploads = [];
|
|
82
82
|
for (const [codebase, { wantBackend, haveBackend }] of Object.entries(payload.functions)) {
|
|
83
|
-
if (shouldUploadBeSkipped(wantBackend, haveBackend)) {
|
|
83
|
+
if (shouldUploadBeSkipped(context, wantBackend, haveBackend)) {
|
|
84
84
|
continue;
|
|
85
85
|
}
|
|
86
86
|
uploads.push(uploadCodebase(context, codebase, wantBackend));
|
|
@@ -88,7 +88,10 @@ async function deploy(context, options, payload) {
|
|
|
88
88
|
await Promise.all(uploads);
|
|
89
89
|
}
|
|
90
90
|
exports.deploy = deploy;
|
|
91
|
-
function shouldUploadBeSkipped(wantBackend, haveBackend) {
|
|
91
|
+
function shouldUploadBeSkipped(context, wantBackend, haveBackend) {
|
|
92
|
+
if (context.filters && context.filters.length > 0) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
92
95
|
const wantEndpoints = backend.allEndpoints(wantBackend);
|
|
93
96
|
const haveEndpoints = backend.allEndpoints(haveBackend);
|
|
94
97
|
if (wantEndpoints.length !== haveEndpoints.length) {
|
|
@@ -167,9 +167,9 @@ class Fabricator {
|
|
|
167
167
|
if (apiFunction.httpsTrigger) {
|
|
168
168
|
apiFunction.httpsTrigger.securityLevel = "SECURE_ALWAYS";
|
|
169
169
|
}
|
|
170
|
-
apiFunction.sourceToken = await scraper.tokenPromise();
|
|
171
170
|
const resultFunction = await this.functionExecutor
|
|
172
171
|
.run(async () => {
|
|
172
|
+
apiFunction.sourceToken = await scraper.getToken();
|
|
173
173
|
const op = await gcf.createFunction(apiFunction);
|
|
174
174
|
return poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `create-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
|
|
175
175
|
})
|
|
@@ -301,9 +301,9 @@ class Fabricator {
|
|
|
301
301
|
throw new Error("Precondition failed");
|
|
302
302
|
}
|
|
303
303
|
const apiFunction = gcf.functionFromEndpoint(endpoint, sourceUrl);
|
|
304
|
-
apiFunction.sourceToken = await scraper.tokenPromise();
|
|
305
304
|
const resultFunction = await this.functionExecutor
|
|
306
305
|
.run(async () => {
|
|
306
|
+
apiFunction.sourceToken = await scraper.getToken();
|
|
307
307
|
const op = await gcf.updateFunction(apiFunction);
|
|
308
308
|
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `update-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
|
|
309
309
|
})
|
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SourceTokenScraper = void 0;
|
|
4
|
+
const error_1 = require("../../../error");
|
|
5
|
+
const functional_1 = require("../../../functional");
|
|
4
6
|
const logger_1 = require("../../../logger");
|
|
5
7
|
class SourceTokenScraper {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.
|
|
8
|
+
constructor(validDurationMs = 1500000) {
|
|
9
|
+
this.tokenValidDurationMs = validDurationMs;
|
|
8
10
|
this.promise = new Promise((resolve) => (this.resolve = resolve));
|
|
11
|
+
this.fetchState = "NONE";
|
|
9
12
|
}
|
|
10
|
-
|
|
11
|
-
if (this.
|
|
12
|
-
this.
|
|
13
|
-
return
|
|
13
|
+
async getToken() {
|
|
14
|
+
if (this.fetchState === "NONE") {
|
|
15
|
+
this.fetchState = "FETCHING";
|
|
16
|
+
return undefined;
|
|
14
17
|
}
|
|
15
|
-
|
|
18
|
+
else if (this.fetchState === "FETCHING") {
|
|
19
|
+
return this.promise;
|
|
20
|
+
}
|
|
21
|
+
else if (this.fetchState === "VALID") {
|
|
22
|
+
if (this.isTokenExpired()) {
|
|
23
|
+
this.fetchState = "FETCHING";
|
|
24
|
+
this.promise = new Promise((resolve) => (this.resolve = resolve));
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
return this.promise;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
(0, functional_1.assertExhaustive)(this.fetchState);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
isTokenExpired() {
|
|
34
|
+
if (this.expiry === undefined) {
|
|
35
|
+
throw new error_1.FirebaseError("Your deployment is checking the expiration of a source token that has not yet been polled. " +
|
|
36
|
+
"Hitting this case should never happen and should be considered a bug. " +
|
|
37
|
+
"Please file an issue at https://github.com/firebase/firebase-tools/issues " +
|
|
38
|
+
"and try deploying your functions again.");
|
|
39
|
+
}
|
|
40
|
+
return Date.now() >= this.expiry;
|
|
16
41
|
}
|
|
17
42
|
get poller() {
|
|
18
43
|
return (op) => {
|
|
@@ -21,6 +46,8 @@ class SourceTokenScraper {
|
|
|
21
46
|
const [, , , region] = ((_c = (_b = op.metadata) === null || _b === void 0 ? void 0 : _b.target) === null || _c === void 0 ? void 0 : _c.split("/")) || [];
|
|
22
47
|
logger_1.logger.debug(`Got source token ${(_d = op.metadata) === null || _d === void 0 ? void 0 : _d.sourceToken} for region ${region}`);
|
|
23
48
|
this.resolve((_e = op.metadata) === null || _e === void 0 ? void 0 : _e.sourceToken);
|
|
49
|
+
this.fetchState = "VALID";
|
|
50
|
+
this.expiry = Date.now() + this.tokenValidDurationMs;
|
|
24
51
|
}
|
|
25
52
|
};
|
|
26
53
|
}
|
|
@@ -51,6 +51,7 @@ function assertBuildEndpoint(ep, id) {
|
|
|
51
51
|
region: "array",
|
|
52
52
|
platform: (platform) => build.AllFunctionsPlatforms.includes(platform),
|
|
53
53
|
entryPoint: "string",
|
|
54
|
+
omit: "Field<boolean>?",
|
|
54
55
|
availableMemoryMb: (mem) => mem === null || isCEL(mem) || build.isValidMemoryOption(mem),
|
|
55
56
|
maxInstances: "Field<number>?",
|
|
56
57
|
minInstances: "Field<number>?",
|
|
@@ -259,7 +260,7 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
|
|
|
259
260
|
if ("serviceAccountEmail" in ep) {
|
|
260
261
|
parsed.serviceAccount = ep.serviceAccountEmail;
|
|
261
262
|
}
|
|
262
|
-
(0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "cpu", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "serviceAccount");
|
|
263
|
+
(0, proto_1.copyIfPresent)(parsed, ep, "omit", "availableMemoryMb", "cpu", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "serviceAccount");
|
|
263
264
|
(0, proto_1.convertIfPresent)(parsed, ep, "secretEnvironmentVariables", (senvs) => {
|
|
264
265
|
if (!senvs) {
|
|
265
266
|
return null;
|
|
@@ -40,12 +40,13 @@ function runCommand(command, childOptions) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
function getChildEnvironment(target, overallOptions, config) {
|
|
43
|
+
var _a;
|
|
43
44
|
const projectId = needProjectId(overallOptions);
|
|
44
45
|
const projectDir = overallOptions.projectRoot;
|
|
45
46
|
let resourceDir;
|
|
46
47
|
switch (target) {
|
|
47
48
|
case "hosting":
|
|
48
|
-
resourceDir = overallOptions.config.path(config.public);
|
|
49
|
+
resourceDir = overallOptions.config.path((_a = config.public) !== null && _a !== void 0 ? _a : config.source);
|
|
49
50
|
break;
|
|
50
51
|
case "functions":
|
|
51
52
|
resourceDir = overallOptions.config.path(config.source);
|