firebase-tools 13.10.0 → 13.10.2
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/commands/dataconnect-sdk-generate.js +5 -9
- package/lib/commands/dataconnect-sql-migrate.js +0 -1
- package/lib/dataconnect/build.js +4 -12
- package/lib/dataconnect/schemaMigration.js +14 -15
- package/lib/deploy/dataconnect/release.js +0 -1
- package/lib/emulator/controller.js +1 -3
- package/lib/emulator/dataconnectEmulator.js +20 -15
- package/lib/emulator/downloadableEmulators.js +26 -12
- package/lib/emulator/portUtils.js +11 -2
- package/lib/init/features/dataconnect/index.js +1 -1
- package/package.json +1 -1
|
@@ -20,16 +20,12 @@ exports.command = new command_1.Command("dataconnect:sdk:generate")
|
|
|
20
20
|
configDir = path.resolve(path.join(cwd), configDir);
|
|
21
21
|
}
|
|
22
22
|
const serviceInfo = await (0, load_1.load)(projectId, service.location, configDir);
|
|
23
|
-
const args = {
|
|
24
|
-
projectId,
|
|
25
|
-
configDir,
|
|
26
|
-
auto_download: true,
|
|
27
|
-
rc: options.rc,
|
|
28
|
-
locationId: service.location,
|
|
29
|
-
};
|
|
30
|
-
const dataconnectEmulator = new dataconnectEmulator_1.DataConnectEmulator(args);
|
|
31
23
|
for (const conn of serviceInfo.connectorInfo) {
|
|
32
|
-
const output = await
|
|
24
|
+
const output = await dataconnectEmulator_1.DataConnectEmulator.generate({
|
|
25
|
+
configDir,
|
|
26
|
+
locationId: service.location,
|
|
27
|
+
connectorId: conn.connectorYaml.connectorId,
|
|
28
|
+
});
|
|
33
29
|
logger_1.logger.info(output);
|
|
34
30
|
logger_1.logger.info(`Generated SDKs for ${conn.connectorYaml.connectorId}`);
|
|
35
31
|
}
|
|
@@ -33,7 +33,6 @@ exports.command = new command_1.Command("dataconnect:sql:migrate [serviceId]")
|
|
|
33
33
|
const diffs = await (0, schemaMigration_1.migrateSchema)({
|
|
34
34
|
options,
|
|
35
35
|
schema: serviceInfo.schema,
|
|
36
|
-
allowNonInteractiveMigration: true,
|
|
37
36
|
validateOnly: true,
|
|
38
37
|
});
|
|
39
38
|
if (diffs.length) {
|
package/lib/dataconnect/build.js
CHANGED
|
@@ -5,19 +5,11 @@ const dataconnectEmulator_1 = require("../emulator/dataconnectEmulator");
|
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const graphqlError_1 = require("./graphqlError");
|
|
7
7
|
async function build(options, configDir) {
|
|
8
|
-
var _a, _b
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
projectId,
|
|
12
|
-
configDir,
|
|
13
|
-
auto_download: true,
|
|
14
|
-
rc: options.rc,
|
|
15
|
-
};
|
|
16
|
-
const dataconnectEmulator = new dataconnectEmulator_1.DataConnectEmulator(args);
|
|
17
|
-
const buildResult = await dataconnectEmulator.build();
|
|
18
|
-
if ((_b = buildResult === null || buildResult === void 0 ? void 0 : buildResult.errors) === null || _b === void 0 ? void 0 : _b.length) {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
const buildResult = await dataconnectEmulator_1.DataConnectEmulator.build({ configDir });
|
|
10
|
+
if ((_a = buildResult === null || buildResult === void 0 ? void 0 : buildResult.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
|
19
11
|
throw new error_1.FirebaseError(`There are errors in your schema and connector files:\n${buildResult.errors.map(graphqlError_1.prettify).join("\n")}`);
|
|
20
12
|
}
|
|
21
|
-
return (
|
|
13
|
+
return (_b = buildResult === null || buildResult === void 0 ? void 0 : buildResult.metadata) !== null && _b !== void 0 ? _b : {};
|
|
22
14
|
}
|
|
23
15
|
exports.build = build;
|
|
@@ -40,7 +40,7 @@ async function diffSchema(schema) {
|
|
|
40
40
|
}
|
|
41
41
|
exports.diffSchema = diffSchema;
|
|
42
42
|
async function migrateSchema(args) {
|
|
43
|
-
const { options, schema,
|
|
43
|
+
const { options, schema, validateOnly } = args;
|
|
44
44
|
const { serviceName, instanceId, instanceName, databaseId } = getIdentifiers(schema);
|
|
45
45
|
await ensureServiceIsConnectedToCloudSql(serviceName, instanceName, databaseId, true);
|
|
46
46
|
try {
|
|
@@ -56,13 +56,8 @@ async function migrateSchema(args) {
|
|
|
56
56
|
if (!incompatible && !invalidConnectors.length) {
|
|
57
57
|
throw err;
|
|
58
58
|
}
|
|
59
|
+
const migrationMode = await promptForSchemaMigration(options, databaseId, incompatible, validateOnly);
|
|
59
60
|
const shouldDeleteInvalidConnectors = await promptForInvalidConnectorError(options, serviceName, invalidConnectors, validateOnly);
|
|
60
|
-
const migrationMode = incompatible
|
|
61
|
-
? await promptForSchemaMigration(options, databaseId, incompatible, allowNonInteractiveMigration)
|
|
62
|
-
: "none";
|
|
63
|
-
if (migrationMode === "none" && incompatible) {
|
|
64
|
-
throw new error_1.FirebaseError("Command aborted.");
|
|
65
|
-
}
|
|
66
61
|
let diffs = [];
|
|
67
62
|
if (incompatible) {
|
|
68
63
|
diffs = await handleIncompatibleSchemaError({
|
|
@@ -143,16 +138,22 @@ async function handleIncompatibleSchemaError(args) {
|
|
|
143
138
|
}
|
|
144
139
|
return [];
|
|
145
140
|
}
|
|
146
|
-
async function promptForSchemaMigration(options, databaseName, err,
|
|
141
|
+
async function promptForSchemaMigration(options, databaseName, err, validateOnly) {
|
|
142
|
+
if (!err) {
|
|
143
|
+
return "none";
|
|
144
|
+
}
|
|
147
145
|
displaySchemaChanges(err);
|
|
148
146
|
if (!options.nonInteractive) {
|
|
147
|
+
if (validateOnly && options.force) {
|
|
148
|
+
return "all";
|
|
149
|
+
}
|
|
149
150
|
const choices = err.destructive
|
|
150
151
|
? [
|
|
151
152
|
{ name: "Execute all changes (including destructive changes)", value: "all" },
|
|
152
153
|
{ name: "Abort changes", value: "none" },
|
|
153
154
|
]
|
|
154
155
|
: [
|
|
155
|
-
{ name: "Execute changes", value: "
|
|
156
|
+
{ name: "Execute changes", value: "all" },
|
|
156
157
|
{ name: "Abort changes", value: "none" },
|
|
157
158
|
];
|
|
158
159
|
return await (0, prompt_1.promptOnce)({
|
|
@@ -161,19 +162,17 @@ async function promptForSchemaMigration(options, databaseName, err, allowNonInte
|
|
|
161
162
|
choices,
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return "none";
|
|
165
|
+
if (!validateOnly) {
|
|
166
|
+
throw new error_1.FirebaseError("Command aborted. Your database schema is incompatible with your Data Connect schema. Run `firebase dataconnect:sql:migrate` to migrate your database schema");
|
|
167
167
|
}
|
|
168
168
|
else if (options.force) {
|
|
169
169
|
return "all";
|
|
170
170
|
}
|
|
171
171
|
else if (!err.destructive) {
|
|
172
|
-
return "
|
|
172
|
+
return "all";
|
|
173
173
|
}
|
|
174
174
|
else {
|
|
175
|
-
|
|
176
|
-
return "none";
|
|
175
|
+
throw new error_1.FirebaseError("Command aborted. This schema migration includes potentially destructive changes. If you'd like to execute it anyway, rerun this command with --force");
|
|
177
176
|
}
|
|
178
177
|
}
|
|
179
178
|
async function promptForInvalidConnectorError(options, serviceName, invalidConnectors, validateOnly) {
|
|
@@ -518,7 +518,6 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
518
518
|
await startEmulator(pubsubEmulator);
|
|
519
519
|
}
|
|
520
520
|
if (listenForEmulator.dataconnect) {
|
|
521
|
-
const dataConnectAddr = legacyGetFirstAddr(types_1.Emulators.DATACONNECT);
|
|
522
521
|
const config = (0, fileUtils_1.readFirebaseJson)(options.config);
|
|
523
522
|
if (!config.length) {
|
|
524
523
|
throw new error_1.FirebaseError("No Data Connect service found in firebase.json");
|
|
@@ -532,8 +531,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
532
531
|
configDir = path.resolve(path.join(cwd), configDir);
|
|
533
532
|
}
|
|
534
533
|
const dataConnectEmulator = new dataconnectEmulator_1.DataConnectEmulator({
|
|
535
|
-
|
|
536
|
-
port: dataConnectAddr.port,
|
|
534
|
+
listen: listenForEmulator.dataconnect,
|
|
537
535
|
projectId,
|
|
538
536
|
auto_download: true,
|
|
539
537
|
configDir,
|
|
@@ -9,16 +9,15 @@ const types_1 = require("./types");
|
|
|
9
9
|
const error_1 = require("../error");
|
|
10
10
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
11
11
|
const types_2 = require("../dataconnect/types");
|
|
12
|
-
const
|
|
12
|
+
const portUtils_1 = require("./portUtils");
|
|
13
13
|
class DataConnectEmulator {
|
|
14
14
|
constructor(args) {
|
|
15
15
|
this.args = args;
|
|
16
16
|
this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT);
|
|
17
17
|
}
|
|
18
18
|
async start() {
|
|
19
|
-
const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATACONNECT);
|
|
20
19
|
this.logger.log("DEBUG", `Using Postgres connection string: ${this.getLocalConectionString()}`);
|
|
21
|
-
const info = await
|
|
20
|
+
const info = await DataConnectEmulator.build({ configDir: this.args.configDir });
|
|
22
21
|
if ((0, types_2.requiresVector)(info.metadata)) {
|
|
23
22
|
if (constants_1.Constants.isDemoProject(this.args.projectId)) {
|
|
24
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.");
|
|
@@ -27,7 +26,7 @@ class DataConnectEmulator {
|
|
|
27
26
|
this.logger.logLabeled("WARN", "Data Connect", "Operations that use vector_embed will make calls to production Vertex AI");
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
|
-
return (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, Object.assign(Object.assign({}, this.args), {
|
|
29
|
+
return (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, Object.assign(Object.assign({}, this.args), { listen: (0, portUtils_1.listenSpecsToString)(this.args.listen), config_dir: this.args.configDir, local_connection_string: this.getLocalConectionString(), project_id: this.args.projectId, service_location: this.args.locationId }));
|
|
31
30
|
}
|
|
32
31
|
connect() {
|
|
33
32
|
return Promise.resolve();
|
|
@@ -36,12 +35,11 @@ class DataConnectEmulator {
|
|
|
36
35
|
return (0, downloadableEmulators_1.stop)(types_1.Emulators.DATACONNECT);
|
|
37
36
|
}
|
|
38
37
|
getInfo() {
|
|
39
|
-
const host = this.args.host || constants_1.Constants.getDefaultHost();
|
|
40
|
-
const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATACONNECT);
|
|
41
38
|
return {
|
|
42
39
|
name: this.getName(),
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
listen: this.args.listen,
|
|
41
|
+
host: this.args.listen[0].address,
|
|
42
|
+
port: this.args.listen[0].port,
|
|
45
43
|
pid: (0, downloadableEmulators_1.getPID)(types_1.Emulators.DATACONNECT),
|
|
46
44
|
timeout: 10000,
|
|
47
45
|
};
|
|
@@ -49,25 +47,32 @@ class DataConnectEmulator {
|
|
|
49
47
|
getName() {
|
|
50
48
|
return types_1.Emulators.DATACONNECT;
|
|
51
49
|
}
|
|
52
|
-
async generate(
|
|
50
|
+
static async generate(args) {
|
|
53
51
|
const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
|
|
54
52
|
const cmd = [
|
|
55
53
|
"generate",
|
|
56
|
-
`--service_location=${
|
|
57
|
-
`--config_dir=${
|
|
58
|
-
`--connector_id=${connectorId}`,
|
|
54
|
+
`--service_location=${args.locationId}`,
|
|
55
|
+
`--config_dir=${args.configDir}`,
|
|
56
|
+
`--connector_id=${args.connectorId}`,
|
|
59
57
|
];
|
|
60
58
|
const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
|
|
61
59
|
if (res.error) {
|
|
62
|
-
throw new error_1.FirebaseError(`Error starting up Data Connect
|
|
60
|
+
throw new error_1.FirebaseError(`Error starting up Data Connect generate: ${res.error.message}`, {
|
|
61
|
+
original: res.error,
|
|
62
|
+
});
|
|
63
63
|
}
|
|
64
64
|
return res.stdout;
|
|
65
65
|
}
|
|
66
|
-
async build() {
|
|
66
|
+
static async build(args) {
|
|
67
67
|
var _a;
|
|
68
68
|
const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
|
|
69
|
-
const cmd = ["build", `--config_dir=${
|
|
69
|
+
const cmd = ["build", `--config_dir=${args.configDir}`];
|
|
70
70
|
const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
|
|
71
|
+
if (res.error) {
|
|
72
|
+
throw new error_1.FirebaseError(`Error starting up Data Connect build: ${res.error.message}`, {
|
|
73
|
+
original: res.error,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
71
76
|
if (res.stderr) {
|
|
72
77
|
throw new error_1.FirebaseError(`Unable to build your Data Connect schema and connectors: ${res.stderr}`);
|
|
73
78
|
}
|
|
@@ -46,15 +46,21 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
46
46
|
},
|
|
47
47
|
dataconnect: process.platform === "darwin"
|
|
48
48
|
? {
|
|
49
|
-
version: "1.1.
|
|
50
|
-
expectedSize:
|
|
51
|
-
expectedChecksum: "
|
|
49
|
+
version: "1.1.19",
|
|
50
|
+
expectedSize: 25836864,
|
|
51
|
+
expectedChecksum: "b31ba00789b82a30f0dee1c03b8f74ce",
|
|
52
52
|
}
|
|
53
|
-
:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
: process.platform === "win32"
|
|
54
|
+
? {
|
|
55
|
+
version: "1.1.19",
|
|
56
|
+
expectedSize: 23629824,
|
|
57
|
+
expectedChecksum: "bcbd7705b36cee72ff0587749d67bfc3",
|
|
58
|
+
}
|
|
59
|
+
: {
|
|
60
|
+
version: "1.1.19",
|
|
61
|
+
expectedSize: 23247120,
|
|
62
|
+
expectedChecksum: "56d6cb2ad85474d3a67999e35d2916a1",
|
|
63
|
+
},
|
|
58
64
|
};
|
|
59
65
|
exports.DownloadDetails = {
|
|
60
66
|
database: {
|
|
@@ -119,14 +125,16 @@ exports.DownloadDetails = {
|
|
|
119
125
|
},
|
|
120
126
|
},
|
|
121
127
|
dataconnect: {
|
|
122
|
-
downloadPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}`),
|
|
128
|
+
downloadPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}${process.platform === "win32" ? ".exe" : ""}`),
|
|
123
129
|
version: EMULATOR_UPDATE_DETAILS.dataconnect.version,
|
|
124
|
-
binaryPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}`),
|
|
130
|
+
binaryPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}${process.platform === "win32" ? ".exe" : ""}`),
|
|
125
131
|
opts: {
|
|
126
132
|
cacheDir: CACHE_DIR,
|
|
127
133
|
remoteUrl: process.platform === "darwin"
|
|
128
134
|
? `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`
|
|
129
|
-
:
|
|
135
|
+
: process.platform === "win32"
|
|
136
|
+
? `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`
|
|
137
|
+
: `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`,
|
|
130
138
|
expectedSize: EMULATOR_UPDATE_DETAILS.dataconnect.expectedSize,
|
|
131
139
|
expectedChecksum: EMULATOR_UPDATE_DETAILS.dataconnect.expectedChecksum,
|
|
132
140
|
skipChecksumAndSize: false,
|
|
@@ -232,7 +240,13 @@ const Commands = {
|
|
|
232
240
|
dataconnect: {
|
|
233
241
|
binary: getExecPath(types_1.Emulators.DATACONNECT),
|
|
234
242
|
args: ["dev"],
|
|
235
|
-
optionalArgs: [
|
|
243
|
+
optionalArgs: [
|
|
244
|
+
"listen",
|
|
245
|
+
"config_dir",
|
|
246
|
+
"local_connection_string",
|
|
247
|
+
"project_id",
|
|
248
|
+
"service_location",
|
|
249
|
+
],
|
|
236
250
|
joinArgs: true,
|
|
237
251
|
shell: true,
|
|
238
252
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveHostAndAssignPorts = exports.waitForPortUsed = exports.checkListenable = void 0;
|
|
3
|
+
exports.listenSpecsToString = exports.resolveHostAndAssignPorts = exports.waitForPortUsed = exports.checkListenable = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const tcpport = require("tcp-port-used");
|
|
6
6
|
const node_net_1 = require("node:net");
|
|
@@ -146,7 +146,7 @@ const EMULATOR_CAN_LISTEN_ON_PRIMARY_ONLY = {
|
|
|
146
146
|
firestore: true,
|
|
147
147
|
"firestore.websocket": true,
|
|
148
148
|
pubsub: true,
|
|
149
|
-
dataconnect:
|
|
149
|
+
dataconnect: false,
|
|
150
150
|
hub: false,
|
|
151
151
|
ui: false,
|
|
152
152
|
auth: true,
|
|
@@ -321,3 +321,12 @@ function listenSpec(lookup, port) {
|
|
|
321
321
|
port: port,
|
|
322
322
|
};
|
|
323
323
|
}
|
|
324
|
+
function listenSpecsToString(specs) {
|
|
325
|
+
return specs
|
|
326
|
+
.map((spec) => {
|
|
327
|
+
const host = spec.family === "IPv4" ? spec.address : `[${spec.address}]`;
|
|
328
|
+
return `${host}:${spec.port}`;
|
|
329
|
+
})
|
|
330
|
+
.join(",");
|
|
331
|
+
}
|
|
332
|
+
exports.listenSpecsToString = listenSpecsToString;
|
|
@@ -45,7 +45,7 @@ async function doSetup(setup, config) {
|
|
|
45
45
|
}
|
|
46
46
|
if (instances.length) {
|
|
47
47
|
cloudSqlInstanceId = await (0, prompt_1.promptOnce)({
|
|
48
|
-
message: `Which
|
|
48
|
+
message: `Which CloudSQL instance would you like to use?`,
|
|
49
49
|
type: "list",
|
|
50
50
|
choices,
|
|
51
51
|
});
|