firebase-tools 13.7.5 → 13.8.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 +9 -1
- package/lib/apiv2.js +19 -13
- package/lib/apphosting/app.js +38 -58
- package/lib/apphosting/githubConnections.js +1 -1
- package/lib/apphosting/index.js +72 -20
- package/lib/checkValidTargetFilters.js +8 -1
- package/lib/commands/apphosting-backends-create.js +4 -3
- package/lib/commands/apphosting-backends-delete.js +24 -17
- package/lib/commands/apphosting-backends-list.js +3 -3
- package/lib/commands/apphosting-secrets-grantaccess.js +9 -5
- package/lib/commands/dataconnect-list.js +64 -0
- package/lib/commands/dataconnect-sdk-generate.js +37 -0
- package/lib/commands/dataconnect-sql-diff.js +25 -0
- package/lib/commands/dataconnect-sql-migrate.js +46 -0
- package/lib/commands/deploy.js +27 -1
- package/lib/commands/index.js +10 -0
- package/lib/commands/init.js +7 -0
- package/lib/commands/setup-emulators-dataconnect.js +12 -0
- package/lib/config.js +1 -0
- package/lib/dataconnect/build.js +23 -0
- package/lib/dataconnect/checkIam.js +30 -0
- package/lib/dataconnect/client.js +115 -0
- package/lib/dataconnect/dataplaneClient.js +16 -0
- package/lib/dataconnect/ensureApis.js +12 -0
- package/lib/dataconnect/fileUtils.js +89 -0
- package/lib/dataconnect/filters.js +45 -0
- package/lib/dataconnect/freeTrial.js +23 -0
- package/lib/dataconnect/graphqlError.js +13 -0
- package/lib/dataconnect/load.js +40 -0
- package/lib/dataconnect/names.js +48 -0
- package/lib/dataconnect/prompts.js +20 -0
- package/lib/dataconnect/provisionCloudSql.js +74 -0
- package/lib/dataconnect/schemaMigration.js +171 -0
- package/lib/dataconnect/types.js +23 -0
- package/lib/deploy/dataconnect/deploy.js +84 -0
- package/lib/deploy/dataconnect/index.js +9 -0
- package/lib/deploy/dataconnect/prepare.js +30 -0
- package/lib/deploy/dataconnect/release.js +65 -0
- package/lib/deploy/functions/checkIam.js +4 -34
- package/lib/deploy/functions/release/fabricator.js +7 -2
- package/lib/deploy/index.js +2 -0
- package/lib/downloadUtils.js +2 -2
- package/lib/emulator/constants.js +3 -0
- package/lib/emulator/controller.js +39 -12
- package/lib/emulator/dataconnectEmulator.js +88 -0
- package/lib/emulator/download.js +1 -1
- package/lib/emulator/downloadableEmulators.js +42 -3
- package/lib/emulator/portUtils.js +3 -3
- package/lib/emulator/registry.js +6 -1
- package/lib/emulator/types.js +3 -0
- package/lib/experiments.js +12 -5
- package/lib/extensions/emulator/specHelper.js +5 -39
- package/lib/frameworks/next/index.js +3 -1
- package/lib/frameworks/next/utils.js +1 -1
- package/lib/gcp/apphosting.js +6 -1
- package/lib/gcp/cloudsql/cloudsqladmin.js +155 -0
- package/lib/gcp/cloudsql/connect.js +128 -0
- package/lib/gcp/cloudsql/fbToolsAuthClient.js +42 -0
- package/lib/gcp/cloudsql/types.js +2 -0
- package/lib/gcp/firedata.js +26 -0
- package/lib/gcp/iam.js +33 -1
- package/lib/gcp/secretManager.js +1 -1
- package/lib/hosting/interactive.js +4 -0
- package/lib/init/features/dataconnect/index.js +160 -0
- package/lib/init/features/emulators.js +13 -0
- package/lib/init/features/functions/index.js +15 -3
- package/lib/init/features/index.js +3 -1
- package/lib/init/index.js +1 -0
- package/lib/logger.js +22 -2
- package/lib/operation-poller.js +8 -2
- package/lib/rc.js +10 -1
- package/lib/requireAuth.js +1 -0
- package/lib/requireTosAcceptance.js +21 -0
- package/lib/utils.js +55 -4
- package/package.json +6 -2
- package/schema/connector-yaml.json +54 -0
- package/schema/dataconnect-yaml.json +72 -0
- package/schema/firebase-config.json +103 -0
- package/templates/extensions/javascript/package.lint.json +2 -2
- package/templates/extensions/javascript/package.nolint.json +2 -2
- package/templates/extensions/typescript/package.lint.json +2 -2
- package/templates/extensions/typescript/package.nolint.json +2 -2
- package/templates/init/dataconnect/connector.yaml +2 -0
- package/templates/init/dataconnect/dataconnect.yaml +10 -0
- package/templates/init/dataconnect/mutations.gql +4 -0
- package/templates/init/dataconnect/queries.gql +6 -0
- package/templates/init/dataconnect/schema.gql +15 -0
- package/templates/init/functions/javascript/_gitignore +2 -1
- package/templates/init/functions/javascript/package.lint.json +2 -2
- package/templates/init/functions/javascript/package.nolint.json +2 -2
- package/templates/init/functions/python/_gitignore +1 -0
- package/templates/init/functions/typescript/_gitignore +1 -0
- package/templates/init/functions/typescript/package.lint.json +2 -2
- package/templates/init/functions/typescript/package.nolint.json +2 -2
|
@@ -14,6 +14,7 @@ exports.DEFAULT_PORTS = {
|
|
|
14
14
|
auth: 9099,
|
|
15
15
|
storage: 9199,
|
|
16
16
|
eventarc: 9299,
|
|
17
|
+
dataconnect: 9399,
|
|
17
18
|
};
|
|
18
19
|
exports.FIND_AVAILBLE_PORT_BY_DEFAULT = {
|
|
19
20
|
ui: true,
|
|
@@ -28,6 +29,7 @@ exports.FIND_AVAILBLE_PORT_BY_DEFAULT = {
|
|
|
28
29
|
storage: false,
|
|
29
30
|
extensions: false,
|
|
30
31
|
eventarc: true,
|
|
32
|
+
dataconnect: true,
|
|
31
33
|
};
|
|
32
34
|
exports.EMULATOR_DESCRIPTION = {
|
|
33
35
|
ui: "Emulator UI",
|
|
@@ -42,6 +44,7 @@ exports.EMULATOR_DESCRIPTION = {
|
|
|
42
44
|
storage: "Storage Emulator",
|
|
43
45
|
extensions: "Extensions Emulator",
|
|
44
46
|
eventarc: "Eventarc Emulator",
|
|
47
|
+
dataconnect: "Data Connect Emulator",
|
|
45
48
|
};
|
|
46
49
|
exports.DEFAULT_HOST = "localhost";
|
|
47
50
|
class Constants {
|
|
@@ -12,14 +12,8 @@ const registry_1 = require("./registry");
|
|
|
12
12
|
const types_1 = require("./types");
|
|
13
13
|
const constants_1 = require("./constants");
|
|
14
14
|
const functionsEmulator_1 = require("./functionsEmulator");
|
|
15
|
-
const auth_1 = require("./auth");
|
|
16
|
-
const databaseEmulator_1 = require("./databaseEmulator");
|
|
17
|
-
const firestoreEmulator_1 = require("./firestoreEmulator");
|
|
18
|
-
const hostingEmulator_1 = require("./hostingEmulator");
|
|
19
|
-
const eventarcEmulator_1 = require("./eventarcEmulator");
|
|
20
15
|
const error_1 = require("../error");
|
|
21
16
|
const projectUtils_1 = require("../projectUtils");
|
|
22
|
-
const pubsubEmulator_1 = require("./pubsubEmulator");
|
|
23
17
|
const commandUtils = require("./commandUtils");
|
|
24
18
|
const hub_1 = require("./hub");
|
|
25
19
|
const hubExport_1 = require("./hubExport");
|
|
@@ -31,10 +25,9 @@ const hubClient_1 = require("./hubClient");
|
|
|
31
25
|
const prompt_1 = require("../prompt");
|
|
32
26
|
const commandUtils_1 = require("./commandUtils");
|
|
33
27
|
const fsutils_1 = require("../fsutils");
|
|
34
|
-
const storage_1 = require("./storage");
|
|
35
28
|
const config_1 = require("./storage/rules/config");
|
|
36
29
|
const getDefaultDatabaseInstance_1 = require("../getDefaultDatabaseInstance");
|
|
37
|
-
const
|
|
30
|
+
const auth_1 = require("../auth");
|
|
38
31
|
const extensionsEmulator_1 = require("./extensionsEmulator");
|
|
39
32
|
const projectConfig_1 = require("../functions/projectConfig");
|
|
40
33
|
const downloadableEmulators_1 = require("./downloadableEmulators");
|
|
@@ -42,6 +35,15 @@ const frameworks_1 = require("../frameworks");
|
|
|
42
35
|
const experiments = require("../experiments");
|
|
43
36
|
const portUtils_1 = require("./portUtils");
|
|
44
37
|
const supported_1 = require("../deploy/functions/runtimes/supported");
|
|
38
|
+
const auth_2 = require("./auth");
|
|
39
|
+
const databaseEmulator_1 = require("./databaseEmulator");
|
|
40
|
+
const eventarcEmulator_1 = require("./eventarcEmulator");
|
|
41
|
+
const dataconnectEmulator_1 = require("./dataconnectEmulator");
|
|
42
|
+
const firestoreEmulator_1 = require("./firestoreEmulator");
|
|
43
|
+
const hostingEmulator_1 = require("./hostingEmulator");
|
|
44
|
+
const pubsubEmulator_1 = require("./pubsubEmulator");
|
|
45
|
+
const storage_1 = require("./storage");
|
|
46
|
+
const fileUtils_1 = require("../dataconnect/fileUtils");
|
|
45
47
|
const START_LOGGING_EMULATOR = utils.envOverride("START_LOGGING_EMULATOR", "false", (val) => val === "true");
|
|
46
48
|
async function exportOnExit(options) {
|
|
47
49
|
const exportOnExitDir = options.exportOnExit;
|
|
@@ -346,7 +348,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
346
348
|
if (emulatorsNotRunning.length > 0 && !constants_1.Constants.isDemoProject(projectId)) {
|
|
347
349
|
functionsLogger.logLabeled("WARN", "functions", `The following emulators are not running, calls to these services from the Functions emulator will affect production: ${clc.bold(emulatorsNotRunning.join(", "))}`);
|
|
348
350
|
}
|
|
349
|
-
const account = (0,
|
|
351
|
+
const account = (0, auth_1.getProjectDefaultAccount)(options.projectRoot);
|
|
350
352
|
const functionsEmulator = new functionsEmulator_1.FunctionsEmulator({
|
|
351
353
|
projectId,
|
|
352
354
|
projectDir,
|
|
@@ -486,13 +488,13 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
486
488
|
throw new error_1.FirebaseError(`Cannot start the ${constants_1.Constants.description(types_1.Emulators.AUTH)} without a project: run 'firebase init' or provide the --project flag`);
|
|
487
489
|
}
|
|
488
490
|
const authAddr = legacyGetFirstAddr(types_1.Emulators.AUTH);
|
|
489
|
-
const authEmulator = new
|
|
491
|
+
const authEmulator = new auth_2.AuthEmulator({
|
|
490
492
|
host: authAddr.host,
|
|
491
493
|
port: authAddr.port,
|
|
492
494
|
projectId,
|
|
493
495
|
singleProjectMode: singleProjectModeEnabled
|
|
494
|
-
?
|
|
495
|
-
:
|
|
496
|
+
? auth_2.SingleProjectMode.WARNING
|
|
497
|
+
: auth_2.SingleProjectMode.NO_WARNING,
|
|
496
498
|
});
|
|
497
499
|
await startEmulator(authEmulator);
|
|
498
500
|
if (exportMetadata.auth) {
|
|
@@ -515,6 +517,31 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
515
517
|
});
|
|
516
518
|
await startEmulator(pubsubEmulator);
|
|
517
519
|
}
|
|
520
|
+
if (listenForEmulator.dataconnect) {
|
|
521
|
+
const dataConnectAddr = legacyGetFirstAddr(types_1.Emulators.DATACONNECT);
|
|
522
|
+
const config = (0, fileUtils_1.readFirebaseJson)(options.config);
|
|
523
|
+
if (!config.length) {
|
|
524
|
+
throw new error_1.FirebaseError("No Data Connect service found in firebase.json");
|
|
525
|
+
}
|
|
526
|
+
else if (config.length > 1) {
|
|
527
|
+
logger_1.logger.warn(`TODO: Add support for multiple services in the Data Connect emulator. Currently emulating first service ${config[0].source}`);
|
|
528
|
+
}
|
|
529
|
+
let configDir = config[0].source;
|
|
530
|
+
if (!path.isAbsolute(configDir)) {
|
|
531
|
+
const cwd = options.cwd || process.cwd();
|
|
532
|
+
configDir = path.resolve(path.join(cwd), configDir);
|
|
533
|
+
}
|
|
534
|
+
const dataConnectEmulator = new dataconnectEmulator_1.DataConnectEmulator({
|
|
535
|
+
host: dataConnectAddr.host,
|
|
536
|
+
port: dataConnectAddr.port,
|
|
537
|
+
projectId,
|
|
538
|
+
auto_download: true,
|
|
539
|
+
configDir,
|
|
540
|
+
locationId: config[0].location,
|
|
541
|
+
rc: options.rc,
|
|
542
|
+
});
|
|
543
|
+
await startEmulator(dataConnectEmulator);
|
|
544
|
+
}
|
|
518
545
|
if (listenForEmulator.storage) {
|
|
519
546
|
const storageAddr = legacyGetFirstAddr(types_1.Emulators.STORAGE);
|
|
520
547
|
const storageEmulator = new storage_1.StorageEmulator({
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataConnectEmulator = void 0;
|
|
4
|
+
const childProcess = require("child_process");
|
|
5
|
+
const api_1 = require("../api");
|
|
6
|
+
const constants_1 = require("./constants");
|
|
7
|
+
const downloadableEmulators_1 = require("./downloadableEmulators");
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
const error_1 = require("../error");
|
|
10
|
+
const emulatorLogger_1 = require("./emulatorLogger");
|
|
11
|
+
const types_2 = require("../dataconnect/types");
|
|
12
|
+
class DataConnectEmulator {
|
|
13
|
+
constructor(args) {
|
|
14
|
+
this.args = args;
|
|
15
|
+
this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT);
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATACONNECT);
|
|
19
|
+
this.logger.log("DEBUG", `Using Postgres connection string: ${this.getLocalConectionString()}`);
|
|
20
|
+
const info = await this.build();
|
|
21
|
+
if ((0, types_2.requiresVector)(info.metadata)) {
|
|
22
|
+
if (constants_1.Constants.isDemoProject(this.args.projectId)) {
|
|
23
|
+
this.logger.logLabeled("WARN", "Data Connect", "Detected a 'demo-' project, but vector embeddings require a real project. Operations that use vector_embed will fail.");
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.logger.logLabeled("WARN", "Data Connect", "Operations that use vector_embed will make calls to production Vertex AI");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, Object.assign(Object.assign({}, this.args), { http_port: port, grpc_port: port + 1, config_dir: this.args.configDir, local_connection_string: this.getLocalConectionString(), project_id: this.args.projectId, service_location: this.args.locationId }));
|
|
30
|
+
}
|
|
31
|
+
connect() {
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
}
|
|
34
|
+
stop() {
|
|
35
|
+
return (0, downloadableEmulators_1.stop)(types_1.Emulators.DATACONNECT);
|
|
36
|
+
}
|
|
37
|
+
getInfo() {
|
|
38
|
+
const host = this.args.host || constants_1.Constants.getDefaultHost();
|
|
39
|
+
const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATACONNECT);
|
|
40
|
+
return {
|
|
41
|
+
name: this.getName(),
|
|
42
|
+
host,
|
|
43
|
+
port,
|
|
44
|
+
pid: (0, downloadableEmulators_1.getPID)(types_1.Emulators.DATACONNECT),
|
|
45
|
+
timeout: 10000,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
getName() {
|
|
49
|
+
return types_1.Emulators.DATACONNECT;
|
|
50
|
+
}
|
|
51
|
+
async generate(connectorId) {
|
|
52
|
+
const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
|
|
53
|
+
const cmd = [
|
|
54
|
+
"generate",
|
|
55
|
+
`--service_location=${this.args.locationId}`,
|
|
56
|
+
`--config_dir=${this.args.configDir}`,
|
|
57
|
+
`--connector_id=${connectorId}`,
|
|
58
|
+
];
|
|
59
|
+
const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
|
|
60
|
+
if (res.error) {
|
|
61
|
+
throw new error_1.FirebaseError(`Error starting up Data Connect emulator: ${res.error}`);
|
|
62
|
+
}
|
|
63
|
+
return res.stdout;
|
|
64
|
+
}
|
|
65
|
+
async build() {
|
|
66
|
+
var _a;
|
|
67
|
+
const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
|
|
68
|
+
const cmd = ["build", `--config_dir=${this.args.configDir}`];
|
|
69
|
+
const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
|
|
70
|
+
if (res.stderr) {
|
|
71
|
+
throw new error_1.FirebaseError(`Unable to build your Data Connect schema and connectors: ${res.stderr}`);
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(res.stdout);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
throw new error_1.FirebaseError(`Unable to parse 'fdc build' output: ${(_a = res.stdout) !== null && _a !== void 0 ? _a : res.stderr}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
getLocalConectionString() {
|
|
81
|
+
var _a, _b;
|
|
82
|
+
if ((0, api_1.dataConnectLocalConnString)()) {
|
|
83
|
+
return (0, api_1.dataConnectLocalConnString)();
|
|
84
|
+
}
|
|
85
|
+
return (_b = (_a = this.args.rc.getDataconnect()) === null || _a === void 0 ? void 0 : _a.postgres) === null || _b === void 0 ? void 0 : _b.localConnectionString;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.DataConnectEmulator = DataConnectEmulator;
|
package/lib/emulator/download.js
CHANGED
|
@@ -15,7 +15,7 @@ async function downloadEmulator(name) {
|
|
|
15
15
|
const emulator = downloadableEmulators.getDownloadDetails(name);
|
|
16
16
|
emulatorLogger_1.EmulatorLogger.forEmulator(name).logLabeled("BULLET", name, `downloading ${path.basename(emulator.downloadPath)}...`);
|
|
17
17
|
fs.ensureDirSync(emulator.opts.cacheDir);
|
|
18
|
-
const tmpfile = await downloadUtils.downloadToTmp(emulator.opts.remoteUrl);
|
|
18
|
+
const tmpfile = await downloadUtils.downloadToTmp(emulator.opts.remoteUrl, !!emulator.opts.auth);
|
|
19
19
|
if (!emulator.opts.skipChecksumAndSize) {
|
|
20
20
|
await validateSize(tmpfile, emulator.opts.expectedSize);
|
|
21
21
|
await validateChecksum(tmpfile, emulator.opts.expectedChecksum);
|
|
@@ -44,6 +44,17 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
44
44
|
expectedSize: 65611398,
|
|
45
45
|
expectedChecksum: "70bb840321423e6ae621a3ae2f314903",
|
|
46
46
|
},
|
|
47
|
+
dataconnect: process.platform === "darwin"
|
|
48
|
+
? {
|
|
49
|
+
version: "1.1.15",
|
|
50
|
+
expectedSize: 25600896,
|
|
51
|
+
expectedChecksum: "36dcf9be7273b9ba6052faf0b3c0347f",
|
|
52
|
+
}
|
|
53
|
+
: {
|
|
54
|
+
version: "1.1.15",
|
|
55
|
+
expectedSize: 23036688,
|
|
56
|
+
expectedChecksum: "e42203947bf984993f295976ee3ba2be",
|
|
57
|
+
},
|
|
47
58
|
};
|
|
48
59
|
exports.DownloadDetails = {
|
|
49
60
|
database: {
|
|
@@ -107,6 +118,22 @@ exports.DownloadDetails = {
|
|
|
107
118
|
namePrefix: "pubsub-emulator",
|
|
108
119
|
},
|
|
109
120
|
},
|
|
121
|
+
dataconnect: {
|
|
122
|
+
downloadPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}`),
|
|
123
|
+
version: EMULATOR_UPDATE_DETAILS.dataconnect.version,
|
|
124
|
+
binaryPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}`),
|
|
125
|
+
opts: {
|
|
126
|
+
cacheDir: CACHE_DIR,
|
|
127
|
+
remoteUrl: process.platform === "darwin"
|
|
128
|
+
? `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`
|
|
129
|
+
: `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`,
|
|
130
|
+
expectedSize: EMULATOR_UPDATE_DETAILS.dataconnect.expectedSize,
|
|
131
|
+
expectedChecksum: EMULATOR_UPDATE_DETAILS.dataconnect.expectedChecksum,
|
|
132
|
+
skipChecksumAndSize: false,
|
|
133
|
+
namePrefix: "dataconnect-emulator",
|
|
134
|
+
auth: true,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
110
137
|
};
|
|
111
138
|
const EmulatorDetails = {
|
|
112
139
|
database: {
|
|
@@ -134,6 +161,11 @@ const EmulatorDetails = {
|
|
|
134
161
|
instance: null,
|
|
135
162
|
stdout: null,
|
|
136
163
|
},
|
|
164
|
+
dataconnect: {
|
|
165
|
+
name: types_1.Emulators.DATACONNECT,
|
|
166
|
+
instance: null,
|
|
167
|
+
stdout: null,
|
|
168
|
+
},
|
|
137
169
|
};
|
|
138
170
|
const Commands = {
|
|
139
171
|
database: {
|
|
@@ -197,6 +229,13 @@ const Commands = {
|
|
|
197
229
|
joinArgs: false,
|
|
198
230
|
shell: false,
|
|
199
231
|
},
|
|
232
|
+
dataconnect: {
|
|
233
|
+
binary: getExecPath(types_1.Emulators.DATACONNECT),
|
|
234
|
+
args: ["dev"],
|
|
235
|
+
optionalArgs: ["http_port", "grpc_port", "config_dir", "local_connection_string", "project_id"],
|
|
236
|
+
joinArgs: true,
|
|
237
|
+
shell: true,
|
|
238
|
+
},
|
|
200
239
|
};
|
|
201
240
|
function getExecPath(name) {
|
|
202
241
|
const details = getDownloadDetails(name);
|
|
@@ -364,10 +403,10 @@ async function stop(targetName) {
|
|
|
364
403
|
exports.stop = stop;
|
|
365
404
|
async function downloadIfNecessary(targetName) {
|
|
366
405
|
const hasEmulator = fs.existsSync(getExecPath(targetName));
|
|
367
|
-
if (hasEmulator) {
|
|
368
|
-
|
|
406
|
+
if (!hasEmulator) {
|
|
407
|
+
await (0, download_1.downloadEmulator)(targetName);
|
|
369
408
|
}
|
|
370
|
-
|
|
409
|
+
return Commands[targetName];
|
|
371
410
|
}
|
|
372
411
|
exports.downloadIfNecessary = downloadIfNecessary;
|
|
373
412
|
async function start(targetName, args, extraEnv = {}) {
|
|
@@ -131,9 +131,8 @@ async function checkListenable(arg1, port) {
|
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
exports.checkListenable = checkListenable;
|
|
134
|
-
async function waitForPortUsed(port, host) {
|
|
135
|
-
const interval =
|
|
136
|
-
const timeout = 60000;
|
|
134
|
+
async function waitForPortUsed(port, host, timeout = 60000) {
|
|
135
|
+
const interval = 200;
|
|
137
136
|
try {
|
|
138
137
|
await tcpport.waitUntilUsedOnHost(port, host, interval, timeout);
|
|
139
138
|
}
|
|
@@ -147,6 +146,7 @@ const EMULATOR_CAN_LISTEN_ON_PRIMARY_ONLY = {
|
|
|
147
146
|
firestore: true,
|
|
148
147
|
"firestore.websocket": true,
|
|
149
148
|
pubsub: true,
|
|
149
|
+
dataconnect: true,
|
|
150
150
|
hub: false,
|
|
151
151
|
ui: false,
|
|
152
152
|
auth: true,
|
package/lib/emulator/registry.js
CHANGED
|
@@ -8,6 +8,7 @@ const constants_1 = require("./constants");
|
|
|
8
8
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
10
|
const apiv2_1 = require("../apiv2");
|
|
11
|
+
const downloadableEmulators_1 = require("./downloadableEmulators");
|
|
11
12
|
class EmulatorRegistry {
|
|
12
13
|
static async start(instance) {
|
|
13
14
|
const description = constants_1.Constants.description(instance.getName());
|
|
@@ -18,7 +19,7 @@ class EmulatorRegistry {
|
|
|
18
19
|
await instance.start();
|
|
19
20
|
if (instance.getName() !== types_1.Emulators.EXTENSIONS) {
|
|
20
21
|
const info = instance.getInfo();
|
|
21
|
-
await portUtils.waitForPortUsed(info.port, (0, utils_1.connectableHostname)(info.host));
|
|
22
|
+
await portUtils.waitForPortUsed(info.port, (0, utils_1.connectableHostname)(info.host), info.timeout);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
static async stop(name) {
|
|
@@ -47,6 +48,7 @@ class EmulatorRegistry {
|
|
|
47
48
|
auth: 3.3,
|
|
48
49
|
storage: 3.5,
|
|
49
50
|
eventarc: 3.6,
|
|
51
|
+
dataconnect: 3.7,
|
|
50
52
|
hub: 4,
|
|
51
53
|
logging: 5,
|
|
52
54
|
};
|
|
@@ -83,6 +85,9 @@ class EmulatorRegistry {
|
|
|
83
85
|
}
|
|
84
86
|
return Object.assign(Object.assign({}, info), { host: (0, utils_1.connectableHostname)(info.host) });
|
|
85
87
|
}
|
|
88
|
+
static getDetails(emulator) {
|
|
89
|
+
return (0, downloadableEmulators_1.get)(emulator);
|
|
90
|
+
}
|
|
86
91
|
static url(emulator, req) {
|
|
87
92
|
const url = new URL("http://unknown/");
|
|
88
93
|
if (req) {
|
package/lib/emulator/types.js
CHANGED
|
@@ -15,6 +15,7 @@ var Emulators;
|
|
|
15
15
|
Emulators["STORAGE"] = "storage";
|
|
16
16
|
Emulators["EXTENSIONS"] = "extensions";
|
|
17
17
|
Emulators["EVENTARC"] = "eventarc";
|
|
18
|
+
Emulators["DATACONNECT"] = "dataconnect";
|
|
18
19
|
})(Emulators = exports.Emulators || (exports.Emulators = {}));
|
|
19
20
|
exports.DOWNLOADABLE_EMULATORS = [
|
|
20
21
|
Emulators.FIRESTORE,
|
|
@@ -22,6 +23,7 @@ exports.DOWNLOADABLE_EMULATORS = [
|
|
|
22
23
|
Emulators.PUBSUB,
|
|
23
24
|
Emulators.UI,
|
|
24
25
|
Emulators.STORAGE,
|
|
26
|
+
Emulators.DATACONNECT,
|
|
25
27
|
];
|
|
26
28
|
exports.IMPORT_EXPORT_EMULATORS = [
|
|
27
29
|
Emulators.FIRESTORE,
|
|
@@ -38,6 +40,7 @@ exports.ALL_SERVICE_EMULATORS = [
|
|
|
38
40
|
Emulators.PUBSUB,
|
|
39
41
|
Emulators.STORAGE,
|
|
40
42
|
Emulators.EVENTARC,
|
|
43
|
+
Emulators.DATACONNECT,
|
|
41
44
|
].filter((v) => v);
|
|
42
45
|
exports.EMULATORS_SUPPORTED_BY_FUNCTIONS = [
|
|
43
46
|
Emulators.FIRESTORE,
|
package/lib/experiments.js
CHANGED
|
@@ -20,11 +20,13 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
20
20
|
rtdbmanagement: {
|
|
21
21
|
shortDescription: "Use new endpoint to administer realtime database instances",
|
|
22
22
|
},
|
|
23
|
-
|
|
24
|
-
shortDescription: "
|
|
25
|
-
fullDescription: "
|
|
26
|
-
"
|
|
27
|
-
"
|
|
23
|
+
functionsv2deployoptimizations: {
|
|
24
|
+
shortDescription: "Optimize deployments of v2 firebase functions",
|
|
25
|
+
fullDescription: "Reuse build images across funtions to increase performance and reliaibility " +
|
|
26
|
+
"of deploys. This has been made an experiment due to backend bugs that are " +
|
|
27
|
+
"temporarily causing failures in some regions with this optimization enabled",
|
|
28
|
+
public: true,
|
|
29
|
+
default: false,
|
|
28
30
|
},
|
|
29
31
|
deletegcfartifacts: {
|
|
30
32
|
shortDescription: `Add the ${(0, colorette_1.bold)("functions:deletegcfartifacts")} command to purge docker build images`,
|
|
@@ -89,6 +91,11 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
89
91
|
default: false,
|
|
90
92
|
public: false,
|
|
91
93
|
},
|
|
94
|
+
dataconnect: {
|
|
95
|
+
shortDescription: "Enable Data Connect related features.",
|
|
96
|
+
fullDescription: "Enable Data Connect related features.",
|
|
97
|
+
public: false,
|
|
98
|
+
},
|
|
92
99
|
});
|
|
93
100
|
function isValidExperiment(name) {
|
|
94
101
|
return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRuntime = exports.DEFAULT_RUNTIME = exports.getFunctionProperties = exports.getFunctionResourcesWithParamSubstitution = exports.
|
|
4
|
-
const yaml = require("yaml");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const fs = require("fs-extra");
|
|
3
|
+
exports.getRuntime = exports.DEFAULT_RUNTIME = exports.getFunctionProperties = exports.getFunctionResourcesWithParamSubstitution = exports.readPostinstall = exports.readExtensionYaml = void 0;
|
|
7
4
|
const supported = require("../../deploy/functions/runtimes/supported");
|
|
8
5
|
const error_1 = require("../../error");
|
|
9
6
|
const extensionsHelper_1 = require("../extensionsHelper");
|
|
10
7
|
const utils_1 = require("../utils");
|
|
8
|
+
const utils_2 = require("../../utils");
|
|
11
9
|
const SPEC_FILE = "extension.yaml";
|
|
12
10
|
const POSTINSTALL_FILE = "POSTINSTALL.md";
|
|
13
11
|
const validFunctionTypes = [
|
|
@@ -15,22 +13,11 @@ const validFunctionTypes = [
|
|
|
15
13
|
"firebaseextensions.v1beta.v2function",
|
|
16
14
|
"firebaseextensions.v1beta.scheduledFunction",
|
|
17
15
|
];
|
|
18
|
-
function wrappedSafeLoad(source) {
|
|
19
|
-
try {
|
|
20
|
-
return yaml.parse(source);
|
|
21
|
-
}
|
|
22
|
-
catch (err) {
|
|
23
|
-
if (err instanceof yaml.YAMLParseError) {
|
|
24
|
-
throw new error_1.FirebaseError(`YAML Error: ${err.message}`, { original: err });
|
|
25
|
-
}
|
|
26
|
-
throw err;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
16
|
async function readExtensionYaml(directory) {
|
|
30
17
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
31
|
-
const extensionYaml = await readFileFromDirectory(directory, SPEC_FILE);
|
|
18
|
+
const extensionYaml = await (0, utils_2.readFileFromDirectory)(directory, SPEC_FILE);
|
|
32
19
|
const source = extensionYaml.source;
|
|
33
|
-
const spec = wrappedSafeLoad(source);
|
|
20
|
+
const spec = (0, utils_2.wrappedSafeLoad)(source);
|
|
34
21
|
spec.params = (_a = spec.params) !== null && _a !== void 0 ? _a : [];
|
|
35
22
|
spec.systemParams = (_b = spec.systemParams) !== null && _b !== void 0 ? _b : [];
|
|
36
23
|
spec.resources = (_c = spec.resources) !== null && _c !== void 0 ? _c : [];
|
|
@@ -44,31 +31,10 @@ async function readExtensionYaml(directory) {
|
|
|
44
31
|
}
|
|
45
32
|
exports.readExtensionYaml = readExtensionYaml;
|
|
46
33
|
async function readPostinstall(directory) {
|
|
47
|
-
const content = await readFileFromDirectory(directory, POSTINSTALL_FILE);
|
|
34
|
+
const content = await (0, utils_2.readFileFromDirectory)(directory, POSTINSTALL_FILE);
|
|
48
35
|
return content.source;
|
|
49
36
|
}
|
|
50
37
|
exports.readPostinstall = readPostinstall;
|
|
51
|
-
function readFileFromDirectory(directory, file) {
|
|
52
|
-
return new Promise((resolve, reject) => {
|
|
53
|
-
fs.readFile(path.resolve(directory, file), "utf8", (err, data) => {
|
|
54
|
-
if (err) {
|
|
55
|
-
if (err.code === "ENOENT") {
|
|
56
|
-
return reject(new error_1.FirebaseError(`Could not find "${file}" in "${directory}"`, { original: err }));
|
|
57
|
-
}
|
|
58
|
-
reject(new error_1.FirebaseError(`Failed to read file "${file}" in "${directory}"`, { original: err }));
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
resolve(data);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}).then((source) => {
|
|
65
|
-
return {
|
|
66
|
-
source,
|
|
67
|
-
sourceDirectory: directory,
|
|
68
|
-
};
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
exports.readFileFromDirectory = readFileFromDirectory;
|
|
72
38
|
function getFunctionResourcesWithParamSubstitution(extensionSpec, params) {
|
|
73
39
|
const rawResources = extensionSpec.resources.filter((resource) => validFunctionTypes.includes(resource.type));
|
|
74
40
|
return (0, extensionsHelper_1.substituteParams)(rawResources, params);
|
|
@@ -400,7 +400,9 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
400
400
|
(0, utils_2.getProductionDistDirFiles)(sourceDir, distDir),
|
|
401
401
|
(0, fs_extra_1.mkdirp)((0, path_1.join)(destDir, distDir)),
|
|
402
402
|
]);
|
|
403
|
-
await Promise.all(productionDistDirfiles.map((file) => (0, fs_extra_1.copy)(
|
|
403
|
+
await Promise.all(productionDistDirfiles.map((file) => (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, distDir, file), (0, path_1.join)(destDir, distDir, file), {
|
|
404
|
+
recursive: true,
|
|
405
|
+
})));
|
|
404
406
|
return { packageJson, frameworksEntry: "next.js", dotEnv };
|
|
405
407
|
}
|
|
406
408
|
exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
|
|
@@ -230,7 +230,7 @@ async function getProductionDistDirFiles(sourceDir, distDir) {
|
|
|
230
230
|
ignore: [(0, path_1.join)("cache", "webpack", "*-development", "**"), (0, path_1.join)("cache", "eslint", "**")],
|
|
231
231
|
cwd: (0, path_1.join)(sourceDir, distDir),
|
|
232
232
|
nodir: true,
|
|
233
|
-
absolute:
|
|
233
|
+
absolute: false,
|
|
234
234
|
realpath: utils_2.IS_WINDOWS,
|
|
235
235
|
}, (err, matches) => {
|
|
236
236
|
if (err)
|
package/lib/gcp/apphosting.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getNextRolloutId = exports.ensureApiEnabled = exports.listLocations = exports.updateTraffic = exports.listRollouts = exports.createRollout = exports.createBuild = exports.listBuilds = exports.getBuild = exports.deleteBackend = exports.listBackends = exports.getBackend = exports.createBackend = exports.serviceAgentEmail = exports.client = exports.API_VERSION = void 0;
|
|
3
|
+
exports.getNextRolloutId = exports.ensureApiEnabled = exports.listLocations = exports.updateTraffic = exports.listRollouts = exports.createRollout = exports.createBuild = exports.listBuilds = exports.getBuild = exports.deleteBackend = exports.listBackends = exports.getBackend = exports.createBackend = exports.parseBackendName = exports.serviceAgentEmail = exports.client = exports.API_VERSION = void 0;
|
|
4
4
|
const proto = require("../gcp/proto");
|
|
5
5
|
const apiv2_1 = require("../apiv2");
|
|
6
6
|
const projectUtils_1 = require("../projectUtils");
|
|
@@ -24,6 +24,11 @@ function serviceAgentEmail(projectNumber) {
|
|
|
24
24
|
return `service-${projectNumber}@${P4SA_DOMAIN}`;
|
|
25
25
|
}
|
|
26
26
|
exports.serviceAgentEmail = serviceAgentEmail;
|
|
27
|
+
function parseBackendName(backendName) {
|
|
28
|
+
const [, projectName, , location, , id] = backendName.split("/");
|
|
29
|
+
return { projectName, location, id };
|
|
30
|
+
}
|
|
31
|
+
exports.parseBackendName = parseBackendName;
|
|
27
32
|
async function createBackend(projectId, location, backendReqBoby, backendId) {
|
|
28
33
|
const res = await exports.client.post(`projects/${projectId}/locations/${location}/backends`, Object.assign(Object.assign({}, backendReqBoby), { labels: Object.assign(Object.assign({}, backendReqBoby.labels), deploymentTool.labels()) }), { queryParams: { backendId } });
|
|
29
34
|
return res.body;
|