firebase-tools 13.20.2 → 13.21.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/apphosting/githubConnections.js +19 -1
- package/lib/apphosting/index.js +12 -46
- package/lib/apphosting/rollout.js +127 -0
- package/lib/command.js +10 -3
- package/lib/commands/apphosting-rollouts-create.js +13 -13
- package/lib/commands/emulators-start.js +1 -1
- package/lib/config.js +14 -4
- package/lib/dataconnect/fileUtils.js +7 -43
- package/lib/dataconnect/freeTrial.js +44 -10
- package/lib/dataconnect/provisionCloudSql.js +4 -4
- package/lib/dataconnect/types.js +3 -2
- package/lib/dataconnect/webhook.js +2 -1
- package/lib/deploy/dataconnect/prepare.js +5 -0
- package/lib/emulator/apphosting/config.js +45 -0
- package/lib/emulator/apphosting/index.js +9 -11
- package/lib/emulator/apphosting/serve.js +16 -10
- package/lib/emulator/apphosting/utils.js +18 -0
- package/lib/emulator/controller.js +6 -1
- package/lib/emulator/downloadableEmulators.js +12 -12
- package/lib/emulator/eventarcEmulator.js +1 -1
- package/lib/emulator/extensionsEmulator.js +38 -6
- package/lib/emulator/functionsEmulator.js +85 -41
- package/lib/emulator/functionsEmulatorShared.js +2 -1
- package/lib/error.js +24 -1
- package/lib/extensions/emulator/triggerHelper.js +1 -1
- package/lib/extensions/extensionsApi.js +11 -8
- package/lib/extensions/runtimes/common.js +11 -19
- package/lib/extensions/runtimes/node.js +25 -22
- package/lib/extensions/types.js +16 -1
- package/lib/gcp/cloudmonitoring.js +3 -3
- package/lib/gcp/devConnect.js +38 -1
- package/lib/init/features/dataconnect/index.js +69 -85
- package/lib/init/features/dataconnect/sdk.js +69 -86
- package/lib/init/spawn.js +2 -1
- package/package.json +1 -1
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AppHostingEmulator = void 0;
|
|
4
|
-
const emulatorLogger_1 = require("../emulatorLogger");
|
|
5
4
|
const types_1 = require("../types");
|
|
6
5
|
const serve_1 = require("./serve");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
7
|
class AppHostingEmulator {
|
|
8
8
|
constructor(args) {
|
|
9
9
|
this.args = args;
|
|
10
|
-
this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.APPHOSTING);
|
|
11
10
|
}
|
|
12
11
|
async start() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.
|
|
16
|
-
|
|
17
|
-
this.logger.logLabeled("INFO", types_1.Emulators.APPHOSTING, `serving on port ${port}`);
|
|
12
|
+
utils_1.logger.logLabeled("INFO", types_1.Emulators.APPHOSTING, "starting apphosting emulator");
|
|
13
|
+
const { hostname, port } = await (0, serve_1.start)();
|
|
14
|
+
this.args.options.host = hostname;
|
|
15
|
+
this.args.options.port = port;
|
|
18
16
|
}
|
|
19
17
|
connect() {
|
|
20
|
-
|
|
18
|
+
utils_1.logger.logLabeled("INFO", types_1.Emulators.APPHOSTING, "connecting apphosting emulator");
|
|
21
19
|
return Promise.resolve();
|
|
22
20
|
}
|
|
23
21
|
stop() {
|
|
24
|
-
|
|
22
|
+
utils_1.logger.logLabeled("INFO", types_1.Emulators.APPHOSTING, "stopping apphosting emulator");
|
|
25
23
|
return Promise.resolve();
|
|
26
24
|
}
|
|
27
25
|
getInfo() {
|
|
28
26
|
return {
|
|
29
27
|
name: types_1.Emulators.APPHOSTING,
|
|
30
|
-
host: this.args.host,
|
|
31
|
-
port: this.args.port,
|
|
28
|
+
host: this.args.options.host,
|
|
29
|
+
port: this.args.options.port,
|
|
32
30
|
};
|
|
33
31
|
}
|
|
34
32
|
getName() {
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.start = void 0;
|
|
4
4
|
const net_1 = require("net");
|
|
5
5
|
const portUtils_1 = require("../portUtils");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const constants_1 = require("../constants");
|
|
6
8
|
const spawn_1 = require("../../init/spawn");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
async function start() {
|
|
11
|
+
const hostname = constants_1.DEFAULT_HOST;
|
|
12
|
+
let port = constants_1.DEFAULT_PORTS.apphosting;
|
|
13
|
+
while (!(await availablePort(hostname, port))) {
|
|
10
14
|
port += 1;
|
|
11
15
|
}
|
|
12
|
-
serve(
|
|
13
|
-
return { port };
|
|
16
|
+
serve(port);
|
|
17
|
+
return { hostname, port };
|
|
14
18
|
}
|
|
15
19
|
exports.start = start;
|
|
20
|
+
async function serve(port) {
|
|
21
|
+
const rootDir = process.cwd();
|
|
22
|
+
const packageManager = await (0, utils_1.discoverPackageManager)(rootDir);
|
|
23
|
+
const apphostingLocalConfig = await (0, config_1.getLocalAppHostingConfiguration)(rootDir);
|
|
24
|
+
await (0, spawn_1.wrapSpawn)(packageManager, ["run", "dev"], rootDir, Object.assign(Object.assign({}, apphostingLocalConfig.environmentVariables), { PORT: port }));
|
|
25
|
+
}
|
|
16
26
|
function availablePort(host, port) {
|
|
17
27
|
return (0, portUtils_1.checkListenable)({
|
|
18
28
|
address: host,
|
|
@@ -20,7 +30,3 @@ function availablePort(host, port) {
|
|
|
20
30
|
family: (0, net_1.isIPv4)(host) ? "IPv4" : "IPv6",
|
|
21
31
|
});
|
|
22
32
|
}
|
|
23
|
-
async function serve(options, port) {
|
|
24
|
-
await (0, spawn_1.wrapSpawn)("npm", ["run", "dev", "--", "-H", options.host, "-p", port], process.cwd());
|
|
25
|
-
}
|
|
26
|
-
exports.serve = serve;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.discoverPackageManager = exports.logger = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const emulatorLogger_1 = require("../emulatorLogger");
|
|
7
|
+
const types_1 = require("../types");
|
|
8
|
+
exports.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.APPHOSTING);
|
|
9
|
+
async function discoverPackageManager(rootdir) {
|
|
10
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(rootdir, "pnpm-lock.yaml"))) {
|
|
11
|
+
return "pnpm";
|
|
12
|
+
}
|
|
13
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(rootdir, "yarn.lock"))) {
|
|
14
|
+
return "yarn";
|
|
15
|
+
}
|
|
16
|
+
return "npm";
|
|
17
|
+
}
|
|
18
|
+
exports.discoverPackageManager = discoverPackageManager;
|
|
@@ -79,6 +79,9 @@ function filterEmulatorTargets(options) {
|
|
|
79
79
|
targets = targets.filter((e) => {
|
|
80
80
|
return options.config.has(e) || options.config.has(`emulators.${e}`);
|
|
81
81
|
});
|
|
82
|
+
if (targets.includes(types_1.Emulators.FUNCTIONS) && !targets.includes(types_1.Emulators.EXTENSIONS)) {
|
|
83
|
+
targets.push(types_1.Emulators.EXTENSIONS);
|
|
84
|
+
}
|
|
82
85
|
const onlyOptions = options.only;
|
|
83
86
|
if (onlyOptions) {
|
|
84
87
|
const only = onlyOptions.split(",").map((o) => {
|
|
@@ -210,6 +213,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
210
213
|
: await (0, projectUtils_1.needProjectNumber)(options);
|
|
211
214
|
const aliases = (0, projectUtils_1.getAliases)(options, projectId);
|
|
212
215
|
extensionEmulator = new extensionsEmulator_1.ExtensionsEmulator({
|
|
216
|
+
options,
|
|
213
217
|
projectId,
|
|
214
218
|
projectDir: options.config.projectDir,
|
|
215
219
|
projectNumber,
|
|
@@ -217,7 +221,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
217
221
|
extensions: options.config.get("extensions"),
|
|
218
222
|
});
|
|
219
223
|
const extensionsBackends = await extensionEmulator.getExtensionBackends();
|
|
220
|
-
const filteredExtensionsBackends = extensionEmulator.filterUnemulatedTriggers(
|
|
224
|
+
const filteredExtensionsBackends = extensionEmulator.filterUnemulatedTriggers(extensionsBackends);
|
|
221
225
|
emulatableBackends.push(...filteredExtensionsBackends);
|
|
222
226
|
(0, track_1.trackGA4)("extensions_emulated", {
|
|
223
227
|
number_of_extensions_emulated: filteredExtensionsBackends.length,
|
|
@@ -374,6 +378,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
374
378
|
debugPort: inspectFunctions,
|
|
375
379
|
verbosity: options.logVerbosity,
|
|
376
380
|
projectAlias: options.projectAlias,
|
|
381
|
+
extensionsEmulator: extensionEmulator,
|
|
377
382
|
});
|
|
378
383
|
await startEmulator(functionsEmulator);
|
|
379
384
|
const eventarcAddr = legacyGetFirstAddr(types_1.Emulators.EVENTARC);
|
|
@@ -37,9 +37,9 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
37
37
|
ui: experiments.isEnabled("emulatoruisnapshot")
|
|
38
38
|
? { version: "SNAPSHOT", expectedSize: -1, expectedChecksum: "" }
|
|
39
39
|
: {
|
|
40
|
-
version: "1.
|
|
41
|
-
expectedSize:
|
|
42
|
-
expectedChecksum: "
|
|
40
|
+
version: "1.14.0",
|
|
41
|
+
expectedSize: 3615311,
|
|
42
|
+
expectedChecksum: "30763ff4a8b81e2c482f05b56799b5c0",
|
|
43
43
|
},
|
|
44
44
|
pubsub: {
|
|
45
45
|
version: "0.8.14",
|
|
@@ -48,20 +48,20 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
48
48
|
},
|
|
49
49
|
dataconnect: process.platform === "darwin"
|
|
50
50
|
? {
|
|
51
|
-
version: "1.
|
|
52
|
-
expectedSize:
|
|
53
|
-
expectedChecksum: "
|
|
51
|
+
version: "1.5.0",
|
|
52
|
+
expectedSize: 25215744,
|
|
53
|
+
expectedChecksum: "670ad771cf36b07c52a71f580df89994",
|
|
54
54
|
}
|
|
55
55
|
: process.platform === "win32"
|
|
56
56
|
? {
|
|
57
|
-
version: "1.
|
|
58
|
-
expectedSize:
|
|
59
|
-
expectedChecksum: "
|
|
57
|
+
version: "1.5.0",
|
|
58
|
+
expectedSize: 25643520,
|
|
59
|
+
expectedChecksum: "b565e4609f08eb2299b7bec7e0cac0dc",
|
|
60
60
|
}
|
|
61
61
|
: {
|
|
62
|
-
version: "1.
|
|
63
|
-
expectedSize:
|
|
64
|
-
expectedChecksum: "
|
|
62
|
+
version: "1.5.0",
|
|
63
|
+
expectedSize: 25129112,
|
|
64
|
+
expectedChecksum: "9a08671b89f557d096c075f6a5ac87db",
|
|
65
65
|
},
|
|
66
66
|
};
|
|
67
67
|
exports.DownloadDetails = {
|
|
@@ -53,7 +53,7 @@ class EventarcEmulator {
|
|
|
53
53
|
const key = `${eventTrigger.eventType}-${channel}`;
|
|
54
54
|
return { projectId, triggerName, eventTrigger, key };
|
|
55
55
|
};
|
|
56
|
-
const removeTriggerRoute = `/emulator/v1/remove/projects/:project_id/triggers/:trigger_name`;
|
|
56
|
+
const removeTriggerRoute = `/emulator/v1/remove/projects/:project_id/triggers/:trigger_name(*)`;
|
|
57
57
|
const removeTriggerHandler = (req, res) => {
|
|
58
58
|
try {
|
|
59
59
|
const { projectId, triggerName, eventTrigger, key } = getTriggerIdentifiers(req);
|
|
@@ -19,10 +19,14 @@ const emulatorLogger_1 = require("./emulatorLogger");
|
|
|
19
19
|
const validation_1 = require("./extensions/validation");
|
|
20
20
|
const registry_1 = require("./registry");
|
|
21
21
|
const types_1 = require("./types");
|
|
22
|
+
const common_1 = require("../extensions/runtimes/common");
|
|
22
23
|
class ExtensionsEmulator {
|
|
23
24
|
constructor(args) {
|
|
24
25
|
this.want = [];
|
|
26
|
+
this.wantDynamic = {};
|
|
25
27
|
this.backends = [];
|
|
28
|
+
this.staticBackends = [];
|
|
29
|
+
this.dynamicBackends = {};
|
|
26
30
|
this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.EXTENSIONS);
|
|
27
31
|
this.pendingDownloads = new Map();
|
|
28
32
|
this.args = args;
|
|
@@ -128,12 +132,40 @@ class ExtensionsEmulator {
|
|
|
128
132
|
this.logger.logLabeled("DEBUG", "Extensions", `Finished "npm run gcp-build" for ${sourceCodePath}`);
|
|
129
133
|
}
|
|
130
134
|
async getExtensionBackends() {
|
|
135
|
+
this.backends = await this.getStaticExtensionBackends();
|
|
136
|
+
for (const backends of Object.values(this.dynamicBackends)) {
|
|
137
|
+
this.backends.push(...backends);
|
|
138
|
+
}
|
|
139
|
+
return this.backends;
|
|
140
|
+
}
|
|
141
|
+
async getStaticExtensionBackends() {
|
|
131
142
|
await this.readManifest();
|
|
132
143
|
await this.checkAndWarnAPIs(this.want);
|
|
133
|
-
this.
|
|
144
|
+
this.staticBackends = await Promise.all(this.want.map((i) => {
|
|
134
145
|
return this.toEmulatableBackend(i);
|
|
135
146
|
}));
|
|
136
|
-
return this.
|
|
147
|
+
return this.staticBackends;
|
|
148
|
+
}
|
|
149
|
+
getDynamicExtensionBackends() {
|
|
150
|
+
const dynamicBackends = [];
|
|
151
|
+
for (const backends of Object.values(this.dynamicBackends)) {
|
|
152
|
+
dynamicBackends.push(...backends);
|
|
153
|
+
}
|
|
154
|
+
return dynamicBackends;
|
|
155
|
+
}
|
|
156
|
+
async addDynamicExtensions(codebase, build) {
|
|
157
|
+
const extensions = (0, common_1.extractExtensionsFromBuilds)({ build });
|
|
158
|
+
this.wantDynamic[codebase] = await planner.wantDynamic({
|
|
159
|
+
projectId: this.args.projectId,
|
|
160
|
+
projectNumber: this.args.projectNumber,
|
|
161
|
+
extensions,
|
|
162
|
+
emulatorMode: true,
|
|
163
|
+
});
|
|
164
|
+
await this.checkAndWarnAPIs(this.wantDynamic[codebase]);
|
|
165
|
+
this.dynamicBackends[codebase] = await Promise.all(this.wantDynamic[codebase].map((i) => {
|
|
166
|
+
return this.toEmulatableBackend(i);
|
|
167
|
+
}));
|
|
168
|
+
await this.getExtensionBackends();
|
|
137
169
|
}
|
|
138
170
|
async toEmulatableBackend(instance) {
|
|
139
171
|
const extensionDir = await this.ensureSourceCode(instance);
|
|
@@ -206,10 +238,10 @@ class ExtensionsEmulator {
|
|
|
206
238
|
}
|
|
207
239
|
}
|
|
208
240
|
}
|
|
209
|
-
filterUnemulatedTriggers(
|
|
241
|
+
filterUnemulatedTriggers(backends) {
|
|
210
242
|
let foundUnemulatedTrigger = false;
|
|
211
243
|
const filteredBackends = backends.filter((backend) => {
|
|
212
|
-
const unemulatedServices = (0, validation_1.checkForUnemulatedTriggerTypes)(backend, options);
|
|
244
|
+
const unemulatedServices = (0, validation_1.checkForUnemulatedTriggerTypes)(backend, this.args.options);
|
|
213
245
|
if (unemulatedServices.length) {
|
|
214
246
|
foundUnemulatedTrigger = true;
|
|
215
247
|
const msg = ` ignored becuase it includes ${unemulatedServices.join(", ")} triggered functions, and the ${unemulatedServices.join(", ")} emulator does not exist or is not running.`;
|
|
@@ -231,9 +263,9 @@ class ExtensionsEmulator {
|
|
|
231
263
|
uiUrl.pathname = `/${types_1.Emulators.EXTENSIONS}/${backend.extensionInstanceId}`;
|
|
232
264
|
return clc.underline(clc.bold(uiUrl.toString()));
|
|
233
265
|
}
|
|
234
|
-
extensionsInfoTable(
|
|
266
|
+
extensionsInfoTable() {
|
|
235
267
|
var _a;
|
|
236
|
-
const filtedBackends = this.filterUnemulatedTriggers(
|
|
268
|
+
const filtedBackends = this.filterUnemulatedTriggers(this.backends);
|
|
237
269
|
const uiRunning = registry_1.EmulatorRegistry.isRunning(types_1.Emulators.UI);
|
|
238
270
|
const tableHead = ["Extension Instance Name", "Extension Ref"];
|
|
239
271
|
if (uiRunning) {
|
|
@@ -81,10 +81,13 @@ class FunctionsEmulator {
|
|
|
81
81
|
this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
|
|
82
82
|
this.multicastTriggers = {};
|
|
83
83
|
this.blockingFunctionsConfig = {};
|
|
84
|
+
this.staticBackends = [];
|
|
85
|
+
this.dynamicBackends = [];
|
|
84
86
|
this.debugMode = false;
|
|
87
|
+
this.staticBackends = args.emulatableBackends;
|
|
85
88
|
emulatorLogger_1.EmulatorLogger.setVerbosity(this.args.verbosity ? emulatorLogger_1.Verbosity[this.args.verbosity] : emulatorLogger_1.Verbosity["DEBUG"]);
|
|
86
89
|
if (this.args.debugPort) {
|
|
87
|
-
const maybeNodeCodebases = this.
|
|
90
|
+
const maybeNodeCodebases = this.staticBackends.filter((b) => !b.runtime || b.runtime.startsWith("node"));
|
|
88
91
|
if (maybeNodeCodebases.length > 1 && typeof this.args.debugPort === "number") {
|
|
89
92
|
throw new error_1.FirebaseError("Cannot debug on a single port with multiple codebases. " +
|
|
90
93
|
"Use --inspect-functions=true to assign dynamic ports to each codebase");
|
|
@@ -96,12 +99,37 @@ class FunctionsEmulator {
|
|
|
96
99
|
this.adminSdkConfig = Object.assign(Object.assign({}, this.args.adminSdkConfig), { projectId: this.args.projectId });
|
|
97
100
|
const mode = this.debugMode ? types_1.FunctionsExecutionMode.SEQUENTIAL : types_1.FunctionsExecutionMode.AUTO;
|
|
98
101
|
this.workerPools = {};
|
|
99
|
-
for (const backend of this.
|
|
102
|
+
for (const backend of this.staticBackends) {
|
|
100
103
|
const pool = new functionsRuntimeWorker_1.RuntimeWorkerPool(mode);
|
|
101
104
|
this.workerPools[backend.codebase] = pool;
|
|
102
105
|
}
|
|
103
106
|
this.workQueue = new workQueue_1.WorkQueue(mode);
|
|
104
107
|
}
|
|
108
|
+
async loadDynamicExtensionBackends() {
|
|
109
|
+
if (this.args.extensionsEmulator) {
|
|
110
|
+
const unfilteredBackends = this.args.extensionsEmulator.getDynamicExtensionBackends();
|
|
111
|
+
this.dynamicBackends =
|
|
112
|
+
this.args.extensionsEmulator.filterUnemulatedTriggers(unfilteredBackends);
|
|
113
|
+
const mode = this.debugMode ? types_1.FunctionsExecutionMode.SEQUENTIAL : types_1.FunctionsExecutionMode.AUTO;
|
|
114
|
+
const credentialEnv = await this.getCredentialsEnvironment();
|
|
115
|
+
for (const backend of this.dynamicBackends) {
|
|
116
|
+
backend.env = Object.assign(Object.assign({}, credentialEnv), backend.env);
|
|
117
|
+
if (this.workerPools[backend.codebase]) {
|
|
118
|
+
if (this.debugMode) {
|
|
119
|
+
this.workerPools[backend.codebase].exit();
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
this.workerPools[backend.codebase].refresh();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const pool = new functionsRuntimeWorker_1.RuntimeWorkerPool(mode);
|
|
127
|
+
this.workerPools[backend.codebase] = pool;
|
|
128
|
+
}
|
|
129
|
+
await this.loadTriggers(backend, true);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
105
133
|
async getCredentialsEnvironment() {
|
|
106
134
|
const credentialEnv = {};
|
|
107
135
|
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
@@ -228,7 +256,7 @@ class FunctionsEmulator {
|
|
|
228
256
|
}
|
|
229
257
|
async start() {
|
|
230
258
|
const credentialEnv = await this.getCredentialsEnvironment();
|
|
231
|
-
for (const e of this.
|
|
259
|
+
for (const e of this.staticBackends) {
|
|
232
260
|
e.env = Object.assign(Object.assign({}, credentialEnv), e.env);
|
|
233
261
|
}
|
|
234
262
|
if (Object.keys(this.adminSdkConfig || {}).length <= 1) {
|
|
@@ -249,7 +277,7 @@ class FunctionsEmulator {
|
|
|
249
277
|
}
|
|
250
278
|
async connect() {
|
|
251
279
|
var _a, _b;
|
|
252
|
-
for (const backend of this.
|
|
280
|
+
for (const backend of this.staticBackends) {
|
|
253
281
|
this.logger.logLabeled("BULLET", "functions", `Watching "${backend.functionsDir}" for Cloud Functions...`);
|
|
254
282
|
const watcher = chokidar.watch(backend.functionsDir, {
|
|
255
283
|
ignored: [
|
|
@@ -315,6 +343,10 @@ class FunctionsEmulator {
|
|
|
315
343
|
};
|
|
316
344
|
const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
|
|
317
345
|
const discoveredBuild = await runtimeDelegate.discoverBuild(runtimeConfig, environment);
|
|
346
|
+
if (discoveredBuild.extensions && this.args.extensionsEmulator) {
|
|
347
|
+
await this.args.extensionsEmulator.addDynamicExtensions(emulatableBackend.codebase, discoveredBuild);
|
|
348
|
+
await this.loadDynamicExtensionBackends();
|
|
349
|
+
}
|
|
318
350
|
const resolution = await (0, build_1.resolveBackend)({
|
|
319
351
|
build: discoveredBuild,
|
|
320
352
|
firebaseConfig: JSON.parse(firebaseConfig),
|
|
@@ -353,6 +385,9 @@ class FunctionsEmulator {
|
|
|
353
385
|
}
|
|
354
386
|
const toRemove = Object.keys(this.triggers).filter((recordKey) => {
|
|
355
387
|
const record = this.getTriggerRecordByKey(recordKey);
|
|
388
|
+
if (record.backend.codebase !== emulatableBackend.codebase) {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
356
391
|
if (force) {
|
|
357
392
|
return true;
|
|
358
393
|
}
|
|
@@ -430,17 +465,17 @@ class FunctionsEmulator {
|
|
|
430
465
|
}
|
|
431
466
|
const ignored = !added;
|
|
432
467
|
this.addTriggerRecord(definition, { backend: emulatableBackend, ignored, url });
|
|
433
|
-
const
|
|
468
|
+
const triggerType = definition.httpsTrigger
|
|
434
469
|
? "http"
|
|
435
470
|
: constants_1.Constants.getServiceName((0, functionsEmulatorShared_1.getFunctionService)(definition));
|
|
436
471
|
if (ignored) {
|
|
437
|
-
const msg = `function ignored because the ${
|
|
472
|
+
const msg = `function ignored because the ${triggerType} emulator does not exist or is not running.`;
|
|
438
473
|
this.logger.logLabeled("BULLET", `functions[${definition.id}]`, msg);
|
|
439
474
|
}
|
|
440
475
|
else {
|
|
441
476
|
const msg = url
|
|
442
|
-
? `${clc.bold(
|
|
443
|
-
: `${clc.bold(
|
|
477
|
+
? `${clc.bold(triggerType)} function initialized (${url}).`
|
|
478
|
+
: `${clc.bold(triggerType)} function initialized.`;
|
|
444
479
|
this.logger.logLabeled("SUCCESS", `functions[${definition.id}]`, msg);
|
|
445
480
|
}
|
|
446
481
|
}
|
|
@@ -483,23 +518,24 @@ class FunctionsEmulator {
|
|
|
483
518
|
}
|
|
484
519
|
}
|
|
485
520
|
}
|
|
486
|
-
addEventarcTrigger(projectId, key, eventTrigger) {
|
|
521
|
+
async addEventarcTrigger(projectId, key, eventTrigger) {
|
|
487
522
|
if (!registry_1.EmulatorRegistry.isRunning(types_1.Emulators.EVENTARC)) {
|
|
488
|
-
return
|
|
523
|
+
return false;
|
|
489
524
|
}
|
|
490
525
|
const bundle = {
|
|
491
526
|
eventTrigger: Object.assign(Object.assign({}, eventTrigger), { service: "eventarc.googleapis.com" }),
|
|
492
527
|
};
|
|
493
528
|
logger_1.logger.debug(`addEventarcTrigger`, JSON.stringify(bundle));
|
|
494
|
-
|
|
495
|
-
.post(`/emulator/v1/projects/${projectId}/triggers/${key}`, bundle)
|
|
496
|
-
|
|
497
|
-
|
|
529
|
+
try {
|
|
530
|
+
await registry_1.EmulatorRegistry.client(types_1.Emulators.EVENTARC).post(`/emulator/v1/projects/${projectId}/triggers/${key}`, bundle);
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
catch (err) {
|
|
498
534
|
this.logger.log("WARN", "Error adding Eventarc function: " + err);
|
|
499
|
-
|
|
500
|
-
|
|
535
|
+
}
|
|
536
|
+
return false;
|
|
501
537
|
}
|
|
502
|
-
removeEventarcTrigger(projectId, key, eventTrigger) {
|
|
538
|
+
async removeEventarcTrigger(projectId, key, eventTrigger) {
|
|
503
539
|
if (!registry_1.EmulatorRegistry.isRunning(types_1.Emulators.EVENTARC)) {
|
|
504
540
|
return Promise.resolve(false);
|
|
505
541
|
}
|
|
@@ -507,45 +543,48 @@ class FunctionsEmulator {
|
|
|
507
543
|
eventTrigger: Object.assign(Object.assign({}, eventTrigger), { service: "eventarc.googleapis.com" }),
|
|
508
544
|
};
|
|
509
545
|
logger_1.logger.debug(`removeEventarcTrigger`, JSON.stringify(bundle));
|
|
510
|
-
|
|
511
|
-
.post(`/emulator/v1/remove/projects/${projectId}/triggers/${key}`, bundle)
|
|
512
|
-
|
|
513
|
-
|
|
546
|
+
try {
|
|
547
|
+
await registry_1.EmulatorRegistry.client(types_1.Emulators.EVENTARC).post(`/emulator/v1/remove/projects/${projectId}/triggers/${key}`, bundle);
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
catch (err) {
|
|
514
551
|
this.logger.log("WARN", "Error removing Eventarc function: " + err);
|
|
515
|
-
|
|
516
|
-
|
|
552
|
+
}
|
|
553
|
+
return false;
|
|
517
554
|
}
|
|
518
|
-
addFirealertsTrigger(projectId, key, eventTrigger) {
|
|
555
|
+
async addFirealertsTrigger(projectId, key, eventTrigger) {
|
|
519
556
|
if (!registry_1.EmulatorRegistry.isRunning(types_1.Emulators.EVENTARC)) {
|
|
520
|
-
return
|
|
557
|
+
return false;
|
|
521
558
|
}
|
|
522
559
|
const bundle = {
|
|
523
560
|
eventTrigger: Object.assign(Object.assign({}, eventTrigger), { service: "firebasealerts.googleapis.com" }),
|
|
524
561
|
};
|
|
525
562
|
logger_1.logger.debug(`addFirealertsTrigger`, JSON.stringify(bundle));
|
|
526
|
-
|
|
527
|
-
.post(`/emulator/v1/projects/${projectId}/triggers/${key}`, bundle)
|
|
528
|
-
|
|
529
|
-
|
|
563
|
+
try {
|
|
564
|
+
await registry_1.EmulatorRegistry.client(types_1.Emulators.EVENTARC).post(`/emulator/v1/projects/${projectId}/triggers/${key}`, bundle);
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
catch (err) {
|
|
530
568
|
this.logger.log("WARN", "Error adding FireAlerts function: " + err);
|
|
531
|
-
|
|
532
|
-
|
|
569
|
+
}
|
|
570
|
+
return false;
|
|
533
571
|
}
|
|
534
|
-
removeFirealertsTrigger(projectId, key, eventTrigger) {
|
|
572
|
+
async removeFirealertsTrigger(projectId, key, eventTrigger) {
|
|
535
573
|
if (!registry_1.EmulatorRegistry.isRunning(types_1.Emulators.EVENTARC)) {
|
|
536
|
-
return
|
|
574
|
+
return false;
|
|
537
575
|
}
|
|
538
576
|
const bundle = {
|
|
539
577
|
eventTrigger: Object.assign(Object.assign({}, eventTrigger), { service: "firebasealerts.googleapis.com" }),
|
|
540
578
|
};
|
|
541
579
|
logger_1.logger.debug(`removeFirealertsTrigger`, JSON.stringify(bundle));
|
|
542
|
-
|
|
543
|
-
.post(`/emulator/v1/remove/projects/${projectId}/triggers/${key}`, bundle)
|
|
544
|
-
|
|
545
|
-
|
|
580
|
+
try {
|
|
581
|
+
await registry_1.EmulatorRegistry.client(types_1.Emulators.EVENTARC).post(`/emulator/v1/remove/projects/${projectId}/triggers/${key}`, bundle);
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
catch (err) {
|
|
546
585
|
this.logger.log("WARN", "Error removing FireAlerts function: " + err);
|
|
547
|
-
|
|
548
|
-
|
|
586
|
+
}
|
|
587
|
+
return false;
|
|
549
588
|
}
|
|
550
589
|
async performPostLoadOperations() {
|
|
551
590
|
if (!this.blockingFunctionsConfig.triggers &&
|
|
@@ -809,9 +848,14 @@ class FunctionsEmulator {
|
|
|
809
848
|
}
|
|
810
849
|
getBackendInfo() {
|
|
811
850
|
const cf3Triggers = this.getCF3Triggers();
|
|
812
|
-
|
|
851
|
+
const backendInfo = this.staticBackends.map((e) => {
|
|
813
852
|
return (0, functionsEmulatorShared_1.toBackendInfo)(e, cf3Triggers);
|
|
814
853
|
});
|
|
854
|
+
const dynamicInfo = this.dynamicBackends.map((e) => {
|
|
855
|
+
return (0, functionsEmulatorShared_1.toBackendInfo)(e, cf3Triggers, { createdBy: "SDK" });
|
|
856
|
+
});
|
|
857
|
+
backendInfo.push(...dynamicInfo);
|
|
858
|
+
return backendInfo;
|
|
815
859
|
}
|
|
816
860
|
getCF3Triggers() {
|
|
817
861
|
return Object.values(this.triggers)
|
|
@@ -1049,7 +1093,7 @@ class FunctionsEmulator {
|
|
|
1049
1093
|
async reloadTriggers() {
|
|
1050
1094
|
this.triggerGeneration++;
|
|
1051
1095
|
this.blockingFunctionsConfig = {};
|
|
1052
|
-
for (const backend of this.
|
|
1096
|
+
for (const backend of this.staticBackends.concat(this.dynamicBackends)) {
|
|
1053
1097
|
await this.loadTriggers(backend);
|
|
1054
1098
|
}
|
|
1055
1099
|
await this.performPostLoadOperations();
|
|
@@ -310,7 +310,7 @@ function getSecretLocalPath(backend, projectDir) {
|
|
|
310
310
|
return path.join(secretDirectory, secretsFile);
|
|
311
311
|
}
|
|
312
312
|
exports.getSecretLocalPath = getSecretLocalPath;
|
|
313
|
-
function toBackendInfo(e, cf3Triggers) {
|
|
313
|
+
function toBackendInfo(e, cf3Triggers, labels) {
|
|
314
314
|
var _a, _b;
|
|
315
315
|
const envWithSecrets = Object.assign({}, e.env);
|
|
316
316
|
for (const s of e.secretEnv) {
|
|
@@ -337,6 +337,7 @@ function toBackendInfo(e, cf3Triggers) {
|
|
|
337
337
|
extension: e.extension,
|
|
338
338
|
extensionVersion: extensionVersion,
|
|
339
339
|
extensionSpec: extensionSpec,
|
|
340
|
+
labels,
|
|
340
341
|
functionTriggers: (_b = e.predefinedTriggers) !== null && _b !== void 0 ? _b : cf3Triggers.filter((t) => t.codebase === e.codebase),
|
|
341
342
|
}));
|
|
342
343
|
}
|
package/lib/error.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isBillingError = exports.FirebaseError = void 0;
|
|
3
|
+
exports.isBillingError = exports.getErrStatus = exports.getErrMsg = exports.FirebaseError = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const DEFAULT_CHILDREN = [];
|
|
6
6
|
const DEFAULT_EXIT = 1;
|
|
@@ -18,6 +18,29 @@ class FirebaseError extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
exports.FirebaseError = FirebaseError;
|
|
21
|
+
function getErrMsg(err, defaultMsg) {
|
|
22
|
+
if (err instanceof Error) {
|
|
23
|
+
return err.message;
|
|
24
|
+
}
|
|
25
|
+
else if (typeof err === "string") {
|
|
26
|
+
return err;
|
|
27
|
+
}
|
|
28
|
+
else if (defaultMsg) {
|
|
29
|
+
return defaultMsg;
|
|
30
|
+
}
|
|
31
|
+
return JSON.stringify(err);
|
|
32
|
+
}
|
|
33
|
+
exports.getErrMsg = getErrMsg;
|
|
34
|
+
function isObject(value) {
|
|
35
|
+
return typeof value === "object" && value !== null;
|
|
36
|
+
}
|
|
37
|
+
function getErrStatus(err, defaultStatus) {
|
|
38
|
+
if (isObject(err) && err.status && typeof err.status === "number") {
|
|
39
|
+
return err.status;
|
|
40
|
+
}
|
|
41
|
+
return defaultStatus || DEFAULT_STATUS;
|
|
42
|
+
}
|
|
43
|
+
exports.getErrStatus = getErrStatus;
|
|
21
44
|
function isBillingError(e) {
|
|
22
45
|
var _a, _b, _c, _d;
|
|
23
46
|
return !!((_d = (_c = (_b = (_a = e.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.details) === null || _d === void 0 ? void 0 : _d.find((d) => {
|
|
@@ -58,7 +58,7 @@ function functionResourceToEmulatedTriggerDefintion(resource, systemParams = {})
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
61
|
-
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS).log("WARN", `Function '${resource.name} is missing a trigger in extension.yaml. Please add one, as triggers defined in code are ignored.`);
|
|
61
|
+
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS).log("WARN", `Function '${resource.name}' is missing a trigger in extension.yaml. Please add one, as triggers defined in code are ignored.`);
|
|
62
62
|
}
|
|
63
63
|
return etd;
|
|
64
64
|
}
|
|
@@ -9,6 +9,7 @@ const error_1 = require("../error");
|
|
|
9
9
|
const logger_1 = require("../logger");
|
|
10
10
|
const operationPoller = require("../operation-poller");
|
|
11
11
|
const refs = require("./refs");
|
|
12
|
+
const types_1 = require("./types");
|
|
12
13
|
const EXTENSIONS_API_VERSION = "v1beta";
|
|
13
14
|
const PAGE_SIZE_MAX = 100;
|
|
14
15
|
const extensionsApiClient = new apiv2_1.Client({
|
|
@@ -81,10 +82,12 @@ exports.deleteInstance = deleteInstance;
|
|
|
81
82
|
async function getInstance(projectId, instanceId) {
|
|
82
83
|
try {
|
|
83
84
|
const res = await extensionsApiClient.get(`/projects/${projectId}/instances/${instanceId}`);
|
|
84
|
-
|
|
85
|
+
if ((0, types_1.isExtensionInstance)(res.body)) {
|
|
86
|
+
return res.body;
|
|
87
|
+
}
|
|
85
88
|
}
|
|
86
89
|
catch (err) {
|
|
87
|
-
if (err
|
|
90
|
+
if ((0, error_1.getErrStatus)(err) === 404) {
|
|
88
91
|
throw new error_1.FirebaseError(`Extension instance '${clc.bold(instanceId)}' not found in project '${clc.bold(projectId)}'.`, { status: 404 });
|
|
89
92
|
}
|
|
90
93
|
throw err;
|
|
@@ -235,7 +238,7 @@ function populateSpec(spec) {
|
|
|
235
238
|
}
|
|
236
239
|
}
|
|
237
240
|
catch (err) {
|
|
238
|
-
logger_1.logger.debug(`[ext] failed to parse resource properties yaml: ${err}`);
|
|
241
|
+
logger_1.logger.debug(`[ext] failed to parse resource properties yaml: ${(0, error_1.getErrMsg)(err)}`);
|
|
239
242
|
}
|
|
240
243
|
}
|
|
241
244
|
spec.params = (_a = spec.params) !== null && _a !== void 0 ? _a : [];
|
|
@@ -281,13 +284,13 @@ async function getExtensionVersion(extensionVersionRef) {
|
|
|
281
284
|
return res.body;
|
|
282
285
|
}
|
|
283
286
|
catch (err) {
|
|
284
|
-
if (err
|
|
287
|
+
if ((0, error_1.getErrStatus)(err) === 404) {
|
|
285
288
|
throw refNotFoundError(ref);
|
|
286
289
|
}
|
|
287
290
|
else if (err instanceof error_1.FirebaseError) {
|
|
288
291
|
throw err;
|
|
289
292
|
}
|
|
290
|
-
throw new error_1.FirebaseError(`Failed to query the extension version '${clc.bold(extensionVersionRef)}': ${err}`);
|
|
293
|
+
throw new error_1.FirebaseError(`Failed to query the extension version '${clc.bold(extensionVersionRef)}': ${(0, error_1.getErrMsg)(err)}`);
|
|
291
294
|
}
|
|
292
295
|
}
|
|
293
296
|
exports.getExtensionVersion = getExtensionVersion;
|
|
@@ -341,14 +344,14 @@ async function getExtension(extensionRef) {
|
|
|
341
344
|
return res.body;
|
|
342
345
|
}
|
|
343
346
|
catch (err) {
|
|
344
|
-
if (err
|
|
347
|
+
if ((0, error_1.getErrStatus)(err) === 404) {
|
|
345
348
|
throw refNotFoundError(ref);
|
|
346
349
|
}
|
|
347
350
|
else if (err instanceof error_1.FirebaseError) {
|
|
348
351
|
throw err;
|
|
349
352
|
}
|
|
350
|
-
throw new error_1.FirebaseError(`Failed to query the extension '${clc.bold(extensionRef)}': ${err}`, {
|
|
351
|
-
status: err
|
|
353
|
+
throw new error_1.FirebaseError(`Failed to query the extension '${clc.bold(extensionRef)}': ${(0, error_1.getErrMsg)(err)}`, {
|
|
354
|
+
status: (0, error_1.getErrStatus)(err),
|
|
352
355
|
});
|
|
353
356
|
}
|
|
354
357
|
}
|